diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
new file mode 100644
index 0000000..8c2c7a4
--- /dev/null
+++ b/.github/workflows/php.yml
@@ -0,0 +1,39 @@
+name: PHP Composer
+
+on:
+ push:
+ branches: [ "main", "refactors" ]
+ pull_request:
+ branches: [ "main", "refactors" ]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: Start PHP Development Server
+ run: php -S localhost:61001 -t public &
+
+ - name: Run ci suite
+ run: composer run-script ci
diff --git a/.gitignore b/.gitignore
index c6ae115..5252a63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,9 @@ app/cache/
.DS_Store
*.sublime-*
biome.*
+.phpunit.result.cache
+node_modules/
+tests/cache/
+.coverage
+.runway-config.json
+apm.db*
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..4b88736
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,2 @@
+composer validate --no-ansi
+composer ci
diff --git a/.runway-config-sample.json b/.runway-config-sample.json
new file mode 100644
index 0000000..1988a6f
--- /dev/null
+++ b/.runway-config-sample.json
@@ -0,0 +1,6 @@
+{
+ "apm": {
+ "source_type": "sqlite",
+ "dest_db_dsn": "sqlite::memory:"
+ }
+}
diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php
index 4f3a78d..6911851 100644
--- a/app/config/bootstrap.php
+++ b/app/config/bootstrap.php
@@ -6,30 +6,20 @@
* for every request made to the application.
*/
-$ds = DIRECTORY_SEPARATOR;
-require_once __DIR__ . $ds . '..' . $ds . '..' . $ds . 'vendor' . $ds . 'autoload.php';
+use app\utils\Config;
-if (file_exists(__DIR__ . $ds . 'config.php') === false) {
+require_once __DIR__ . '/../../vendor/autoload.php';
+
+if (!file_exists(__DIR__ . '/config.php')) {
Flight::halt(500, 'Config file not found. Please create a config.php file in the app/config directory to get started.');
}
-// this has to be hard code required because autoload hasn't been registered yet.
-require_once __DIR__ . $ds . '..' . $ds . 'utils' . $ds . 'CustomFlight.php';
-
-// It is better practice to not use static methods for everything. It makes your
-// app much more difficult to unit test easily.
-$app = Flight::app();
-
/*
* Load the config file
* P.S. When you require a php file and that file returns an array, the array
* will be returned by the require statement where you can assign it to a var.
*/
-$config = require __DIR__ . $ds . 'config.php';
-$app->set('config', $config);
-
-// Whip out the ol' router and we'll pass that to the routes file
-$router = $app->router();
+Flight::set('config', new Config(require __DIR__ . '/config.php'));
/*
* Load the routes file. the $router variable above is passed into the routes.php
@@ -38,7 +28,7 @@
* When someone hits that URL, you point them to a function or method
* that will handle the request.
*/
-require_once __DIR__ . $ds . 'routes.php';
+require_once __DIR__ . '/routes.php';
/*
* You additionally could just define the routes in this file. It's up to you.
@@ -63,11 +53,12 @@
* That's a discussion for another day. Suffice to say, that Flight has a basic concept
* of a services container by registering classes to the Engine class.
*/
-require_once __DIR__ . $ds . 'services.php';
+require_once __DIR__ . '/services.php';
// At this point, your app should have all the instructions it needs and it'll
// "start" processing everything. This is where the magic happens.
-$app->start();
+Flight::start();
+
/*
.----..---. .--. .----. .---. .---. .-. .-. .--. .---. .----. .-. .-..----. .----..-. .-.
{ {__ {_ _}/ {} \ | {} }{_ _} {_ _}| {_} | / {} \{_ _} | {} }| { } || {} }| {} }\ \/ /
diff --git a/app/config/config_sample.php b/app/config/config_sample.php
index bed8e7d..a4d9eb5 100644
--- a/app/config/config_sample.php
+++ b/app/config/config_sample.php
@@ -1,5 +1,6 @@
path(__DIR__ . $ds . '..' . $ds . '..');
-$app->set('flight.base_url', '/'); // if this is in a subdirectory, you'll need to change this
-$app->set('flight.case_sensitive', false); // if you want case sensitive routes, set this to true
-$app->set('flight.log_errors', true); // if you want to log errors, set this to true
-$app->set('flight.handle_errors', false); // if you want flight to handle errors, set this to true
-$app->set('flight.views.path', __DIR__ . $ds . '..' . $ds . 'views'); // set the path to your view/template/ui files
-$app->set('flight.views.extension', '.php'); // set the file extension for your view/template/ui files
-$app->set('flight.content_length', true); // if flight should send a content length header
+Flight::set('flight.handle_errors', false); // if you want flight to handle errors, set this to true
+Flight::set('flight.views.path', __DIR__ . '/../views'); // set the path to your view/template/ui files
/*
* Get Tracy up and running
@@ -44,15 +28,16 @@
* https://tracy.nette.org/
*/
Debugger::enable(); // auto tries to figure out your environment
-// Debugger::enable(Debugger::DEVELOPMENT) // sometimes you have to be explicit (also Debugger::PRODUCTION)
+// Debugger::enable(Debugger::Development); // sometimes you have to be explicit (also Debugger::Production)
// Debugger::enable('23.75.345.200'); // you can also provide an array of IP addresses
-Debugger::$logDirectory = __DIR__ . $ds . '..' . $ds . 'log';
+Debugger::$logDirectory = __DIR__ . '/../log';
Debugger::$strictMode = true; // display all errors
// Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // all errors except deprecated notices
+// if Debugger bar is visible, then content-length can not be set by Flight
if (Debugger::$showBar) {
- $app->set('flight.content_length', false); // if Debugger bar is visible, then content-length can not be set by Flight
- new TracyExtensionLoader($app);
+ Flight::set('flight.content_length', false);
+ (new Container)->get(TracyExtensionLoader::class);
}
/*
diff --git a/app/config/routes.php b/app/config/routes.php
index 368be70..255bcaf 100644
--- a/app/config/routes.php
+++ b/app/config/routes.php
@@ -4,101 +4,175 @@
use app\middleware\HeaderSecurityMiddleware;
use app\utils\DocsLogic;
use app\utils\Translator;
-use app\utils\CustomEngine;
-use flight\net\Router;
+use flight\Container;
-/** @var CustomEngine $app */
-/** @var Router $router */
+Flight::route('GET /api/status', static fn() => Flight::json(['status' => 'ok']));
// This acts like a global middleware
-$router->group('', function (Router $router) use ($app) {
-
- /*
- * Specific routes
- */
- // This processes github webhooks
- $router->post('/update-stuff', [DocsController::class, 'updateStuffPost'], false, 'update_stuff');
-
- /*
- * Redirects
- */
- // if theres no language or version in the url, redirect and default to en and v3
- $app->route('/', function () use ($app) {
- // pull out the default language by the accept header
- $language = Translator::getLanguageFromRequest();
- $app->redirect('/'.$language.'/v3/');
- });
-
- // If the route only defines a language (ex: /en) redirect with a version
- $app->route('/@language:[a-z0-9]{2}', function (string $language) use ($app): void {
- // if there's a number in it, it's actually probably the version so we'll need to pull the language out and consider this a version
- if (preg_match('/\d/', $language) === 1) {
- $version = $language;
- $language = Translator::getLanguageFromRequest();
- $app->redirect("/en/$language/");
- } else {
- $version = 'v3';
- }
- $app->redirect("/$language/$version/");
- });
-
- // Pick up old routes that didn't use to have a language and version header
- $app->route('/@section:[\w\-]{3,}(/@sub_section:[\w\-]{3,})', function (string $section, ?string $sub_section = '') use ($app): void {
- $language = Translator::getLanguageFromRequest();
- $app->redirect("/{$language}/v3/$section/$sub_section");
- });
-
- /*
- * Core routes
- */
- $app->group('/@language:[a-z]{2}/@version:[a-z0-9]{2}', function (Router $router) use ($app): void {
- $router->get('/', [DocsController::class, 'aboutGet'], false, 'about');
- $router->get('/single-page', [DocsController::class, 'singlePageGet'], false, 'single_page');
- $router->get('/about', [DocsController::class, 'aboutGet']);
- $router->get('/install', [DocsController::class, 'installGet'], false, 'install');
-
- // Unique URL workaround because this is the only 'single page' with a scrollspy for the time being.
- $router->get('/install/install', function () use ($app): void {
- $app->redirect($app->getUrl('install'));
- });
-
- $router->get('/license', [DocsController::class, 'licenseGet'], false, 'license');
- $router->get('/examples', [DocsController::class, 'examplesGet'], false, 'examples');
- $router->get('/media', [DocsController::class, 'mediaGet'], false, 'media');
- $router->get('/search', [DocsController::class, 'searchGet'], false, 'search');
-
- $router->group('/learn', function (Router $router): void {
- $router->get('', [DocsController::class, 'learnGet'], false, 'learn');
- $router->get('/@section_name', [DocsController::class, 'learnSectionsGet']);
- });
-
- $router->group('/guides', function (Router $router): void {
- $router->get('', [DocsController::class, 'guidesGet'], false, 'guides');
- $router->get('/@section_name', [DocsController::class, 'guidesSectionsGet']);
- });
-
- $router->group('/awesome-plugins', function (Router $router): void {
- $router->get('', [DocsController::class, 'awesomePluginsGet'], false, 'awesome_plugins');
- $router->get('/@plugin_name', [DocsController::class, 'pluginGet'], false, 'plugin');
- });
- });
-}, [ new HeaderSecurityMiddleware() ]);
+Flight::group('', static function (): void {
+ /*
+ * Specific routes
+ */
+ // This processes github webhooks
+ Flight::route(
+ pattern: 'POST /update-stuff',
+ callback: [DocsController::class, 'updateStuffPost'],
+ alias: 'update_stuff'
+ );
+
+ /*
+ * Redirects
+ */
+ // if theres no language or version in the url, redirect and default to en
+ // and v3
+ Flight::route('/', static function (): void {
+ // pull out the default language by the accept header
+ $language = Translator::getLanguageFromRequest();
+
+ Flight::redirect("/$language/v3/");
+ });
+
+ // If the route only defines a language (ex: /en) redirect with a version
+ Flight::route(
+ '/@language:[a-z0-9]{2}',
+ static function (string $language): void {
+ // if there's a number in it, it's actually probably the version so
+ // we'll need to pull the language out and consider this a version
+ $version = preg_match('/\d/', $language) ? $language : 'v3';
+
+ if (preg_match('/\d/', $language)) {
+ $language = Translator::getLanguageFromRequest();
+ Flight::redirect("/en/$language/");
+ }
+
+ Flight::redirect("/$language/$version/");
+ }
+ );
+
+ // Pick up old routes that didn't use to have a language and version header
+ Flight::route(
+ '/@section:[\w\-]{3,}(/@sub_section:[\w\-]{3,})',
+ static function (string $section, ?string $sub_section = ''): void {
+ $language = Translator::getLanguageFromRequest();
+
+ Flight::redirect("/$language/v3/$section/$sub_section/");
+ }
+ );
+
+ /*
+ * Core routes
+ */
+ Flight::group(
+ '/@language:[a-z]{2}/@version:[a-z0-9]{2}',
+ static function (): void {
+ Flight::route(
+ pattern: 'GET /',
+ callback: [DocsController::class, 'aboutGet'],
+ alias: 'about'
+ );
+
+ Flight::route(
+ pattern: 'GET /single-page',
+ callback: [DocsController::class, 'singlePageGet'],
+ alias: 'single_page'
+ );
+
+ Flight::route('GET /about', [DocsController::class, 'aboutGet']);
+
+ Flight::route(
+ pattern: 'GET /install',
+ callback: [DocsController::class, 'installGet'],
+ alias: 'install'
+ );
+
+ // Unique URL workaround because this is the only 'single page'
+ // with a scrollspy for the time being.
+ Flight::route('GET /install/install', static function (): void {
+ Flight::redirect(Flight::getUrl('install'));
+ });
+
+ Flight::route(
+ pattern: 'GET /license',
+ callback: [DocsController::class, 'licenseGet'],
+ alias: 'license'
+ );
+
+ Flight::route(
+ pattern: 'GET /examples',
+ callback: [DocsController::class, 'examplesGet'],
+ alias: 'examples'
+ );
+
+ Flight::route(
+ pattern: 'GET /media',
+ callback: [DocsController::class, 'mediaGet'],
+ alias: 'media'
+ );
+
+ Flight::route(
+ pattern: 'GET /search',
+ callback: [DocsController::class, 'searchGet'],
+ alias: 'search'
+ );
+
+ Flight::group('/learn', static function (): void {
+ Flight::route(
+ pattern: 'GET ',
+ callback: [DocsController::class, 'learnGet'],
+ alias: 'learn'
+ );
+
+ Flight::route(
+ 'GET /@section_name',
+ [DocsController::class, 'learnSectionsGet']
+ );
+ });
+
+ Flight::group('/guides', static function (): void {
+ Flight::route(
+ pattern: 'GET /',
+ callback: [DocsController::class, 'guidesGet'],
+ alias: 'guides'
+ );
+
+ Flight::route(
+ 'GET /@section_name',
+ [DocsController::class, 'guidesSectionsGet']
+ );
+ });
+
+ Flight::group('/awesome-plugins', static function (): void {
+ Flight::route(
+ pattern: 'GET /',
+ callback: [DocsController::class, 'awesomePluginsGet'],
+ alias: 'awesome_plugins'
+ );
+
+ Flight::route(
+ pattern: 'GET /@plugin_name',
+ callback: [DocsController::class, 'pluginGet'],
+ alias: 'plugin'
+ );
+ });
+ }
+ );
+}, [HeaderSecurityMiddleware::class]);
/*
* 404 Handler
*/
-$app->map('notFound', function () use ($app): void {
- // Clear out anything that may have been generated
- $app->response()->clearBody()->status(404);
-
- // pull the version out of the URL
- $url = $app->request()->url;
- $version = preg_match('~/(v\d)/~', $url, $matches) === 1 ? $matches[1] : 'v3';
-
- (new DocsLogic($app))->renderPage('not_found.latte', [
- 'title' => '404 Not Found',
- 'version' => $version
- ]);
- $app->response()->send();
- exit;
+Flight::map('notFound', static function (): void {
+ // Clear out anything that may have been generated
+ Flight::response()->clearBody()->status(404);
+
+ // pull the version out of the URL
+ $url = Flight::request()->url;
+ $version = preg_match('~/(v\d)/~', $url, $matches) ? $matches[1] : 'v3';
+
+ (new Container)->get(DocsLogic::class)->renderPage('not_found.latte', [
+ 'title' => '404 Not Found',
+ 'version' => $version
+ ]);
+
+ Flight::response()->send();
});
diff --git a/app/config/services.php b/app/config/services.php
index 3e2bc9a..5874376 100644
--- a/app/config/services.php
+++ b/app/config/services.php
@@ -1,25 +1,21 @@
register('translator', Translator::class);
+// This translates some common parts of the page, not the content
+Flight::register('translator', Translator::class);
// Templating Engine used to render the views
-$app->register('latte', LatteEngine::class, [], function (LatteEngine $latte) use ($app): void {
+Flight::register('latte', LatteEngine::class, [], static function (LatteEngine $latte): void {
$latte->setTempDirectory(__DIR__ . '/../cache/');
$latte->setLoader(new FileLoader(__DIR__ . '/../views/'));
- $translator = $app->translator();
+ $translator = Flight::translator();
$translatorExtension = new TranslatorExtension(
[$translator, 'translate'],
@@ -29,9 +25,14 @@
});
// Cache for storing parsedown and other things
-$app->register('cache', Cache::class, [__DIR__ . '/../cache/'], function (Cache $cache) {
+Flight::register('cache', Cache::class, [__DIR__ . '/../cache/'], static function (Cache $cache): void {
$cache->setDevMode(ENVIRONMENT === 'development');
});
// Parsedown is a markdown parser
-$app->register('parsedown', Parsedown::class);
+Flight::register('parsedown', Parsedown::class);
+
+// Register the APM
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance(Flight::app());
diff --git a/app/controllers/DocsController.php b/app/controllers/DocsController.php
index 83355f2..19fe8e5 100644
--- a/app/controllers/DocsController.php
+++ b/app/controllers/DocsController.php
@@ -6,6 +6,7 @@
use app\utils\DocsLogic;
use app\utils\Text;
use Exception;
+use flight\core\EventDispatcher;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
@@ -155,6 +156,16 @@ public function pluginGet(string $language, string $version, string $plugin_name
public function singlePageGet(string $language, string $version) {
$app = $this->app;
+ // Check if the language is valid
+ if ($this->DocsLogic->checkValidLanguage($language) === false) {
+ $language = 'en';
+ }
+
+ // Check if the version is valid
+ if ($this->DocsLogic->checkValidVersion($version) === false) {
+ $version = 'v3';
+ }
+
// recursively look through all the content files, and pull out each section and render it
$sections = [];
$language_directory = self::CONTENT_DIR . '/' . $version . '/' . $language . '/';
@@ -171,17 +182,23 @@ public function singlePageGet(string $language, string $version) {
$Translator = $this->DocsLogic->setupTranslatorService($language, $version);
- $markdown_html = $app->cache()->refreshIfExpired('single_page_html_' . $language . '_' . $version, function () use ($app, $sections, $Translator) {
- $markdown_html = '';
-
- foreach ($sections as $section) {
+ $cacheHit = true;
+ $cacheStartTime = microtime(true);
+ $cacheKey = 'single_page_html_' . $language . '_' . $version;
+ $markdown_html = $app->cache()->retrieve($cacheKey);
+ if ($markdown_html === null) {
+ $cacheHit = false;
+ $markdown_html = '';
+ foreach ($sections as $section) {
$slugged_section = Text::slugify($section);
$markdown_html .= '
';
$markdown_html .= $app->parsedown()->text($Translator->getMarkdownLanguageFile($section . '.md'));
}
- return $markdown_html;
- }, 86400); // 1 day
+ $app->cache()->store($cacheKey, $markdown_html, 86400); // 1 day
+ }
+
+ $app->eventDispatcher()->trigger('flight.cache.checked', 'single_page_get_'.$cacheKey, $cacheHit, microtime(true) - $cacheStartTime);
$this->DocsLogic->renderPage('single_page.latte', [
'page_title' => 'single_page_documentation',
diff --git a/app/utils/Config.php b/app/utils/Config.php
new file mode 100644
index 0000000..da15d60
--- /dev/null
+++ b/app/utils/Config.php
@@ -0,0 +1,10 @@
+app->request();
$uri = $request->url;
@@ -37,75 +47,109 @@ public function renderPage(string $latte_file, array $params = []) {
$this->app->latte()->render($latte_file, $params);
}
- /**
- * Sets up the translator service with the specified language and version.
- *
- * @param string $language The language to be used by the translator.
- * @param string $version The version of the translation service.
- * @return Translator The configured translator service.
- */
- public function setupTranslatorService(string $language, string $version): Translator {
- $Translator = $this->app->translator();
- $Translator->setLanguage($language);
- $Translator->setVersion($version);
+ /**
+ * Sets up the translator service with the specified language and version.
+ *
+ * @param string $language The language to be used by the translator.
+ * @param string $version The version of the translation service.
+ * @return Translator The configured translator service.
+ */
+ public function setupTranslatorService(string $language, string $version): Translator {
+ $Translator = $this->app->translator();
+ $Translator->setLanguage($language);
+ $Translator->setVersion($version);
return $Translator;
- }
-
- /**
- * Compiles a single page based on the specified language, version, and section.
- *
- * @param string $language The language of the page to compile.
- * @param string $version The version of the page to compile.
- * @param string $section The section of the page to compile.
- *
- * @return void
- */
+ }
+
+ /**
+ * Compiles a single page based on the specified language, version, and section.
+ *
+ * @param string $language The language of the page to compile.
+ * @param string $version The version of the page to compile.
+ * @param string $section The section of the page to compile.
+ *
+ * @return void
+ */
public function compileSinglePage(string $language, string $version, string $section) {
$app = $this->app;
- $Translator = $this->setupTranslatorService($language, $version);
+ // Check if the language is valid
+ if ($this->checkValidLanguage($language) === false) {
+ $language = 'en';
+ }
+
+ // Check if the version is valid
+ if ($this->checkValidVersion($version) === false) {
+ $version = 'v3';
+ }
+
+ $Translator = $this->setupTranslatorService($language, $version);
+
+ $cacheStartTime = microtime(true);
+ $cacheHit = true;
+ $cacheKey = $section . '_html_' . $language . '_' . $version;
+ $markdown_html = $app->cache()->retrieve($cacheKey);
+ if ($markdown_html === null) {
+ $cacheHit = false;
+ $markdown_html = $app->parsedown()->text($Translator->getMarkdownLanguageFile($section . '.md'));
+ $markdown_html = Text::addClassesToElements($markdown_html);
+ $app->cache()->store($cacheKey, $markdown_html, 86400); // 1 day
+ }
- $markdown_html = $app->cache()->refreshIfExpired($section . '_html_' . $language . '_' . $version, function() use ($app, $section, $Translator) {
- $markdown_html = $app->parsedown()->text($Translator->getMarkdownLanguageFile($section . '.md'));
- $markdown_html = Text::addClassesToElements($markdown_html);
- return $markdown_html;
- }, 86400); // 1 day
+ $app->eventDispatcher()->trigger('flight.cache.checked', 'compile_single_page_' . $cacheKey, $cacheHit, microtime(true) - $cacheStartTime);
$markdown_html = $this->wrapContentInDiv($markdown_html);
$this->renderPage('single_page.latte', [
'page_title' => $section,
'markdown' => $markdown_html,
- 'version' => $version,
+ 'version' => $version,
]);
}
- /**
- * Compiles the Scrollspy page based on the provided language, version, section, and sub-section.
- *
- * @param string $language The language of the documentation.
- * @param string $version The version of the documentation.
- * @param string $section The main section of the documentation.
- * @param string $sub_section The sub-section of the documentation.
- */
+ /**
+ * Compiles the Scrollspy page based on the provided language, version, section, and sub-section.
+ *
+ * @param string $language The language of the documentation.
+ * @param string $version The version of the documentation.
+ * @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) {
$app = $this->app;
- $Translator = $this->setupTranslatorService($language, $version);
+ // Check if the language is valid
+ if ($this->checkValidLanguage($language) === false) {
+ $language = 'en';
+ }
+
+ // Check if the version is valid
+ if ($this->checkValidVersion($version) === false) {
+ $version = 'v3';
+ }
+
+ $Translator = $this->setupTranslatorService($language, $version);
$section_file_path = str_replace('_', '-', $section);
$sub_section_underscored = str_replace('-', '_', $sub_section);
$heading_data = $app->cache()->retrieve($sub_section_underscored . '_heading_data_' . $language . '_' . $version);
- $markdown_html = $app->cache()->refreshIfExpired($sub_section_underscored . '_html_' . $language . '_' . $version, function () use ($app, $section_file_path, $sub_section, $sub_section_underscored, &$heading_data, $language, $Translator, $version) {
- $parsed_text = $app->parsedown()->text($Translator->getMarkdownLanguageFile('/' . $section_file_path . '/' . $sub_section_underscored . '.md'));
+
+ $cacheStartTime = microtime(true);
+ $cacheHit = true;
+ $cacheKey = $sub_section_underscored . '_html_' . $language . '_' . $version;
+ $markdown_html = $app->cache()->retrieve($cacheKey);
+ if ($markdown_html === null) {
+ $cacheHit = false;
+ $markdown_html = $app->parsedown()->text($Translator->getMarkdownLanguageFile('/' . $section_file_path . '/' . $sub_section_underscored . '.md'));
$heading_data = [];
- $parsed_text = Text::generateAndConvertHeaderListFromHtml($parsed_text, $heading_data, 'h2', $section_file_path.'/'.$sub_section);
- $parsed_text = Text::addClassesToElements($parsed_text);
+ $markdown_html = Text::generateAndConvertHeaderListFromHtml($markdown_html, $heading_data, 'h2', $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
+ }
- return $parsed_text;
- }, 86400); // 1 day
+ $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 = '';
@@ -123,17 +167,17 @@ public function compileScrollspyPage(string $language, string $version, string $
'custom_page_title' => ($page_title ? $page_title . ' - ' : '') . $Translator->translate($section),
'markdown' => $markdown_html,
'heading_data' => $heading_data,
- 'relative_uri' => '/'.$section_file_path,
- 'version' => $version,
+ 'relative_uri' => '/' . $section_file_path,
+ 'version' => $version,
]);
}
- /**
+ /**
* 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
+ *
+ * @param string $html
+ * @return string
*/
protected function wrapContentInDiv(string $html): string {
$dom = new DOMDocument;
@@ -179,8 +223,8 @@ protected function wrapContentInDiv(string $html): string {
&& $element->nodeName !== 'ol'
&& $element->nodeName !== 'ul'
&& $element->nodeName !== 'blockquote'
- && $element->nodeName !== 'table'
- && $element->nodeName !== 'dl'
+ && $element->nodeName !== 'table'
+ && $element->nodeName !== 'dl'
&& is_null($div) === false
) {
$d .= '';
@@ -198,4 +242,24 @@ protected function wrapContentInDiv(string $html): string {
return $d;
}
-}
\ No newline at end of file
+
+ /**
+ * Checks if the provided language is valid.
+ *
+ * @param string $language The language code to check.
+ * @return bool True if the language is valid, false otherwise.
+ */
+ public function checkValidLanguage(string $language): bool {
+ return in_array($language, self::AVAILABLE_LANGUAGES, true) === true;
+ }
+
+ /**
+ * Checks if the provided version is valid.
+ *
+ * @param string $version The version code to check.
+ * @return bool True if the version is valid, false otherwise.
+ */
+ public function checkValidVersion(string $version): bool {
+ return in_array($version, ['v3', 'v2'], true) === true;
+ }
+}
diff --git a/app/utils/Text.php b/app/utils/Text.php
index 50fb6d3..4e6b814 100644
--- a/app/utils/Text.php
+++ b/app/utils/Text.php
@@ -40,7 +40,7 @@ public static function slugify(string $text): string {
* @param string $section_file_path [description]
* @return string
*/
- public static function generateAndConvertHeaderListFromHtml(string $markdown_html, array &$heading_data = [], $heading_tag = 'h1', string $section_file_path): string {
+ public static function generateAndConvertHeaderListFromHtml(string $markdown_html, array &$heading_data = [], $heading_tag = 'h1', string $section_file_path = ''): string {
$markdown_html = preg_replace_callback('/(\<' . $heading_tag . '(.*?))\>(.*)(<\/' . $heading_tag . '>)/i', function ($matches) use (&$heading_data, $section_file_path) {
if (! stripos($matches[0], 'id=')) {
$title = strip_tags($matches[3]);
diff --git a/app/views/banner.latte b/app/views/banner.latte
index 0e9b13d..3e2ed2d 100644
--- a/app/views/banner.latte
+++ b/app/views/banner.latte
@@ -2,11 +2,11 @@
@@ -21,11 +21,11 @@
diff --git a/app/views/links.latte b/app/views/links.latte
index c9d1028..2f7a5d6 100644
--- a/app/views/links.latte
+++ b/app/views/links.latte
@@ -15,15 +15,15 @@
-
+
{foreach ['en', 'fr', 'es', 'pt', 'lv', 'de', 'ru', 'zh', 'ja', 'ko', 'uk', 'id'] as $lang}
{/foreach}
-
+
+ src="/js/color-mode-toggler.js">
diff --git a/app/views/logo.latte b/app/views/logo.latte
index ce85e0a..62c30f0 100644
--- a/app/views/logo.latte
+++ b/app/views/logo.latte
@@ -1,12 +1,12 @@
diff --git a/app/views/scripts.latte b/app/views/scripts.latte
index e59644e..46eaea3 100644
--- a/app/views/scripts.latte
+++ b/app/views/scripts.latte
@@ -1,6 +1,6 @@
+ src="/js/color-mode-toggler.js">
-
+
diff --git a/composer.json b/composer.json
index 0f5e313..daadd7e 100644
--- a/composer.json
+++ b/composer.json
@@ -7,15 +7,23 @@
{
"name": "n0nag0n",
"email": "n0nag0n@sky-9.com"
+ },
+ {
+ "homepage": "https://faslatam.42web.io",
+ "name": "fadrian06",
+ "role": "Contributor"
}
],
"require": {
"php": "^8.2",
"ext-json": "*",
"erusev/parsedown": "^1.7",
+ "flightphp/apm": "^0.2",
"flightphp/cache": "^1.0",
- "flightphp/core": "^3.13",
+ "flightphp/container": "^1.1",
+ "flightphp/core": "^3.15",
"latte/latte": "^3.0",
+ "symfony/polyfill-mbstring": "^1.31",
"tracy/tracy": "^2.10"
},
"config": {
@@ -29,16 +37,42 @@
"pre-install-cmd": [
"composer check-platform-reqs"
],
+ "post-autoload-dump": [
+ "php -r \"if (!file_exists('app/config/config.php')) copy('app/config/config_sample.php', 'app/config/config.php');\"",
+ "php -r \"if (!file_exists('.runway-config.json')) copy('.runway-config-sample.json', '.runway-config.json');\""
+ ],
"pre-update-cmd": [
"composer check-platform-reqs"
],
"start": "[ -x \"$(command -v php8.2)\" ] && php8.2 -S localhost:8000 -t public || php -S localhost:8000 -t public",
- "rector": "rector"
+ "ci": [
+ "composer check-platform-reqs --no-ansi",
+ "phpunit --colors=never --no-progress",
+ "phpstan --no-progress --no-ansi"
+ ],
+ "serve": [
+ "Composer\\Config::disableProcessTimeout",
+ "php -S 0.0.0.0:61001 -t public"
+ ]
},
"require-dev": {
"flightphp/tracy-extensions": "^0.2.3",
+ "guzzlehttp/guzzle": "^7.9",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.1",
- "rector/rector": "^2.0"
+ "phpstan/phpstan-deprecation-rules": "^2.0",
+ "phpunit/phpunit": "^11.5",
+ "rector/rector": "^2.0",
+ "symfony/var-dumper": "^7.2"
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "app\\": "app"
+ }
}
}
diff --git a/composer.lock b/composer.lock
index ca5f8cd..cbc0c0c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,81 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4ce80b4eab67752b32503d45cadfe450",
+ "content-hash": "bf9add3a4513451895feac750eeb3bd5",
"packages": [
+ {
+ "name": "adhocore/cli",
+ "version": "v1.9.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/adhocore/php-cli.git",
+ "reference": "86be16e3c3b42d76fcdb32529bcded0fedb925d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/adhocore/php-cli/zipball/86be16e3c3b42d76fcdb32529bcded0fedb925d3",
+ "reference": "86be16e3c3b42d76fcdb32529bcded0fedb925d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Ahc\\Cli\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jitendra Adhikari",
+ "email": "jiten.adhikary@gmail.com"
+ }
+ ],
+ "description": "Command line interface library for PHP",
+ "keywords": [
+ "argument-parser",
+ "argv-parser",
+ "cli",
+ "cli-action",
+ "cli-app",
+ "cli-color",
+ "cli-option",
+ "cli-writer",
+ "command",
+ "console",
+ "console-app",
+ "php-cli",
+ "php8",
+ "stream-input",
+ "stream-output"
+ ],
+ "support": {
+ "issues": "https://github.com/adhocore/php-cli/issues",
+ "source": "https://github.com/adhocore/php-cli/tree/v1.9.3"
+ },
+ "funding": [
+ {
+ "url": "https://paypal.me/ji10",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/adhocore",
+ "type": "github"
+ }
+ ],
+ "time": "2024-12-04T03:40:29+00:00"
+ },
{
"name": "erusev/parsedown",
"version": "1.7.4",
@@ -56,6 +129,72 @@
},
"time": "2019-12-30T22:54:17+00:00"
},
+ {
+ "name": "flightphp/apm",
+ "version": "v0.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/flightphp/apm.git",
+ "reference": "a9eb6b09b543cc19200586165fb98ed0adc0aab8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/flightphp/apm/zipball/a9eb6b09b543cc19200586165fb98ed0adc0aab8",
+ "reference": "a9eb6b09b543cc19200586165fb98ed0adc0aab8",
+ "shasum": ""
+ },
+ "require": {
+ "flightphp/core": "^3.15",
+ "flightphp/runway": "^0.2 || ^1.1",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "enqueue/redis": "^0.10.19",
+ "n0nag0n/simple-job-queue": "^1.1",
+ "phpunit/phpunit": "^9.0",
+ "rregeer/phpunit-coverage-check": "^0.3.1",
+ "squizlabs/php_codesniffer": "^3.8"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "flight\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "n0nag0n",
+ "email": "n0nag0n@sky-9.com",
+ "role": "Owner"
+ }
+ ],
+ "description": "High Performance Application Performance Monitoring (APM) for FlightPHP",
+ "homepage": "https://docs.flightphp.com",
+ "keywords": [
+ "Application performance monitor",
+ "Simple",
+ "apm",
+ "application",
+ "application performance",
+ "application performance monitoring",
+ "flight",
+ "lightweight",
+ "monitor",
+ "monitoring",
+ "performance",
+ "performance monitoring",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/flightphp/apm/issues",
+ "source": "https://github.com/flightphp/apm/tree/v0.2.1"
+ },
+ "time": "2025-03-18T05:33:13+00:00"
+ },
{
"name": "flightphp/cache",
"version": "1.0.0",
@@ -110,18 +249,66 @@
},
"time": "2025-02-21T14:03:10+00:00"
},
+ {
+ "name": "flightphp/container",
+ "version": "v1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/flightphp/container.git",
+ "reference": "207f0dad0841e9c24f7fcc51b6755ed4ba3b8028"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/flightphp/container/zipball/207f0dad0841e9c24f7fcc51b6755ed4ba3b8028",
+ "reference": "207f0dad0841e9c24f7fcc51b6755ed4ba3b8028",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4",
+ "psr/container": "^2.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "rector/rector": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "flight\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "fadrian06",
+ "email": "franyeradriansanchez@gmail.com"
+ }
+ ],
+ "description": "FlightPHP Dependency Injection Container",
+ "support": {
+ "issues": "https://github.com/flightphp/container/issues",
+ "source": "https://github.com/flightphp/container/tree/v1.1.0"
+ },
+ "time": "2025-03-13T06:01:12+00:00"
+ },
{
"name": "flightphp/core",
- "version": "v3.14.0",
+ "version": "v3.15.2",
"source": {
"type": "git",
"url": "https://github.com/flightphp/core.git",
- "reference": "2762daf4f4725eae784291ac4ef21b04a6863be6"
+ "reference": "0abf1b9b169a6d3f1010ab9b1acc0d8fb139be3d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/flightphp/core/zipball/2762daf4f4725eae784291ac4ef21b04a6863be6",
- "reference": "2762daf4f4725eae784291ac4ef21b04a6863be6",
+ "url": "https://api.github.com/repos/flightphp/core/zipball/0abf1b9b169a6d3f1010ab9b1acc0d8fb139be3d",
+ "reference": "0abf1b9b169a6d3f1010ab9b1acc0d8fb139be3d",
"shasum": ""
},
"require": {
@@ -133,14 +320,15 @@
},
"require-dev": {
"ext-pdo_sqlite": "*",
+ "flightphp/container": "^1.0",
"flightphp/runway": "^0.2.3 || ^1.0",
"league/container": "^4.2",
"level-2/dice": "^4.0",
- "phpstan/extension-installer": "^1.3",
- "phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^9.5",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpunit/phpunit": "^9.6",
"rregeer/phpunit-coverage-check": "^0.3.1",
- "squizlabs/php_codesniffer": "^3.8"
+ "squizlabs/php_codesniffer": "^3.11"
},
"suggest": {
"latte/latte": "Latte template engine",
@@ -167,7 +355,7 @@
{
"name": "Franyer Sánchez",
"email": "franyeradriansanchez@gmail.com",
- "homepage": "https://faslatam.000webhostapp.com",
+ "homepage": "https://faslatam.42web.io",
"role": "Maintainer"
},
{
@@ -180,9 +368,61 @@
"homepage": "http://flightphp.com",
"support": {
"issues": "https://github.com/flightphp/core/issues",
- "source": "https://github.com/flightphp/core/tree/v3.14.0"
+ "source": "https://github.com/flightphp/core/tree/v3.15.2"
+ },
+ "time": "2025-03-15T05:22:55+00:00"
+ },
+ {
+ "name": "flightphp/runway",
+ "version": "v1.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/flightphp/runway.git",
+ "reference": "b88c1901b77eda935ef475af772445c3108cf23f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/flightphp/runway/zipball/b88c1901b77eda935ef475af772445c3108cf23f",
+ "reference": "b88c1901b77eda935ef475af772445c3108cf23f",
+ "shasum": ""
+ },
+ "require": {
+ "adhocore/cli": "^1.7",
+ "nette/php-generator": "^4.1",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.3",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.5",
+ "rregeer/phpunit-coverage-check": "^0.3.1",
+ "squizlabs/php_codesniffer": "^3.8"
+ },
+ "bin": [
+ "runway"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "flight\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "n0nag0n",
+ "email": "n0nag0n@sky-9.com"
+ }
+ ],
+ "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"
},
- "time": "2025-02-21T17:42:57+00:00"
+ "time": "2025-01-11T17:52:47+00:00"
},
{
"name": "latte/latte",
@@ -271,54 +511,49 @@
"time": "2024-10-08T00:58:27+00:00"
},
{
- "name": "tracy/tracy",
- "version": "v2.10.9",
+ "name": "nette/php-generator",
+ "version": "v4.1.7",
"source": {
"type": "git",
- "url": "https://github.com/nette/tracy.git",
- "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26"
+ "url": "https://github.com/nette/php-generator.git",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/tracy/zipball/e7af75205b184ca8895bc57fafd331f8d5022d26",
- "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/d201c9bc217e0969d1b678d286be49302972fb56",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "ext-session": "*",
+ "nette/utils": "^3.2.9 || ^4.0",
"php": "8.0 - 8.4"
},
- "conflict": {
- "nette/di": "<3.0"
- },
"require-dev": {
- "latte/latte": "^2.5 || ^3.0",
- "nette/di": "^3.0",
- "nette/http": "^3.0",
- "nette/mail": "^3.0 || ^4.0",
- "nette/tester": "^2.2",
- "nette/utils": "^3.0 || ^4.0",
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.4",
+ "nikic/php-parser": "^4.18 || ^5.0",
"phpstan/phpstan": "^1.0",
- "psr/log": "^1.0 || ^2.0 || ^3.0"
+ "tracy/tracy": "^2.8"
+ },
+ "suggest": {
+ "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.10-dev"
+ "dev-master": "4.1-dev"
}
},
"autoload": {
- "files": [
- "src/Tracy/functions.php"
- ],
"classmap": [
- "src"
+ "src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
],
"authors": [
{
@@ -330,46 +565,61 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.",
- "homepage": "https://tracy.nette.org",
+ "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.4 features.",
+ "homepage": "https://nette.org",
"keywords": [
- "Xdebug",
- "debug",
- "debugger",
+ "code",
"nette",
- "profiler"
+ "php",
+ "scaffolding"
],
"support": {
- "issues": "https://github.com/nette/tracy/issues",
- "source": "https://github.com/nette/tracy/tree/v2.10.9"
+ "issues": "https://github.com/nette/php-generator/issues",
+ "source": "https://github.com/nette/php-generator/tree/v4.1.7"
},
- "time": "2024-11-07T14:48:00+00:00"
- }
- ],
- "packages-dev": [
+ "time": "2024-11-29T01:41:18+00:00"
+ },
{
- "name": "flightphp/tracy-extensions",
- "version": "v0.2.3",
+ "name": "nette/utils",
+ "version": "v4.0.5",
"source": {
"type": "git",
- "url": "https://github.com/flightphp/tracy-extensions.git",
- "reference": "a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5"
+ "url": "https://github.com/nette/utils.git",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/flightphp/tracy-extensions/zipball/a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5",
- "reference": "a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5",
+ "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
"shasum": ""
},
"require": {
- "flightphp/core": "^3.0",
- "php": ">=8.0",
- "tracy/tracy": "^2.10"
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "nette/finder": "<3",
+ "nette/schema": "<1.2.2"
},
"require-dev": {
- "ghostff/session": "^2.1"
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "ext-gd": "to use Image",
+ "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
+ "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
+ "ext-json": "to use Nette\\Utils\\Json",
+ "ext-mbstring": "to use Strings::lower() etc...",
+ "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
"autoload": {
"classmap": [
"src/"
@@ -377,196 +627,2888 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
],
"authors": [
{
- "name": "n0nag0n",
- "email": "n0nag0n@sky-9.com"
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
}
],
- "description": "A few Flight specific extensions for Tracy Debugger to help debug your code quickly.",
+ "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "array",
+ "core",
+ "datetime",
+ "images",
+ "json",
+ "nette",
+ "paginator",
+ "password",
+ "slugify",
+ "string",
+ "unicode",
+ "utf-8",
+ "utility",
+ "validation"
+ ],
"support": {
- "issues": "https://github.com/flightphp/tracy-extensions/issues",
- "source": "https://github.com/flightphp/tracy-extensions/tree/v0.2.3"
+ "issues": "https://github.com/nette/utils/issues",
+ "source": "https://github.com/nette/utils/tree/v4.0.5"
},
- "time": "2024-03-12T05:14:20+00:00"
+ "time": "2024-08-07T15:39:19+00:00"
},
{
- "name": "phpstan/extension-installer",
- "version": "1.4.3",
+ "name": "psr/container",
+ "version": "2.0.2",
"source": {
"type": "git",
- "url": "https://github.com/phpstan/extension-installer.git",
- "reference": "85e90b3942d06b2326fba0403ec24fe912372936"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936",
- "reference": "85e90b3942d06b2326fba0403ec24fe912372936",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
- "composer-plugin-api": "^2.0",
- "php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.9.0 || ^2.0"
- },
- "require-dev": {
- "composer/composer": "^2.0",
- "php-parallel-lint/php-parallel-lint": "^1.2.0",
- "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
+ "php": ">=7.4.0"
},
- "type": "composer-plugin",
+ "type": "library",
"extra": {
- "class": "PHPStan\\ExtensionInstaller\\Plugin"
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
},
"autoload": {
"psr-4": {
- "PHPStan\\ExtensionInstaller\\": "src/"
+ "Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "Composer plugin for automatic installation of PHPStan extensions",
- "keywords": [
- "dev",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "tracy/tracy",
+ "version": "v2.10.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tracy.git",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tracy/zipball/e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-session": "*",
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "nette/di": "<3.0"
+ },
+ "require-dev": {
+ "latte/latte": "^2.5 || ^3.0",
+ "nette/di": "^3.0",
+ "nette/http": "^3.0",
+ "nette/mail": "^3.0 || ^4.0",
+ "nette/tester": "^2.2",
+ "nette/utils": "^3.0 || ^4.0",
+ "phpstan/phpstan": "^1.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.10-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Tracy/functions.php"
+ ],
+ "classmap": [
+ "src"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.",
+ "homepage": "https://tracy.nette.org",
+ "keywords": [
+ "Xdebug",
+ "debug",
+ "debugger",
+ "nette",
+ "profiler"
+ ],
+ "support": {
+ "issues": "https://github.com/nette/tracy/issues",
+ "source": "https://github.com/nette/tracy/tree/v2.10.9"
+ },
+ "time": "2024-11-07T14:48:00+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "flightphp/tracy-extensions",
+ "version": "v0.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/flightphp/tracy-extensions.git",
+ "reference": "a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/flightphp/tracy-extensions/zipball/a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5",
+ "reference": "a4ebcd97e96a3db432f77a8f3b7f38ffe2c45cc5",
+ "shasum": ""
+ },
+ "require": {
+ "flightphp/core": "^3.0",
+ "php": ">=8.0",
+ "tracy/tracy": "^2.10"
+ },
+ "require-dev": {
+ "ghostff/session": "^2.1"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "n0nag0n",
+ "email": "n0nag0n@sky-9.com"
+ }
+ ],
+ "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.3"
+ },
+ "time": "2024-03-12T05:14:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.9.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "d281ed313b989f213357e3be1a179f02196ac99b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
+ "reference": "d281ed313b989f213357e3be1a179f02196ac99b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.3",
+ "guzzlehttp/psr7": "^2.7.0",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "guzzle/client-integration-tests": "3.0.2",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.9.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-24T11:22:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-10-17T10:06:22+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "0.9.0",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.7.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-18T11:15:46+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.13.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "024473a478be9df5fdaca2c793f2232fe788e414"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
+ "reference": "024473a478be9df5fdaca2c793f2232fe788e414",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-12T12:17:51+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "447a020a1f875a434d62f2a401f53b82a396e494"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
+ "reference": "447a020a1f875a434d62f2a401f53b82a396e494",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
+ },
+ "time": "2024-12-30T11:07:19+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpstan/extension-installer",
+ "version": "1.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/extension-installer.git",
+ "reference": "85e90b3942d06b2326fba0403ec24fe912372936"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936",
+ "reference": "85e90b3942d06b2326fba0403ec24fe912372936",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.9.0 || ^2.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.0",
+ "php-parallel-lint/php-parallel-lint": "^1.2.0",
+ "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPStan\\ExtensionInstaller\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\ExtensionInstaller\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Composer plugin for automatic installation of PHPStan extensions",
+ "keywords": [
+ "dev",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/phpstan/extension-installer/issues",
+ "source": "https://github.com/phpstan/extension-installer/tree/1.4.3"
+ },
+ "time": "2024-09-04T20:21:43+00:00"
+ },
+ {
+ "name": "phpstan/phpstan",
+ "version": "2.1.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan.git",
+ "reference": "f9adff3b87c03b12cc7e46a30a524648e497758f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f9adff3b87c03b12cc7e46a30a524648e497758f",
+ "reference": "f9adff3b87c03b12cc7e46a30a524648e497758f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
+ },
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPStan - PHP Static Analysis Tool",
+ "keywords": [
+ "dev",
"static analysis"
],
"support": {
- "issues": "https://github.com/phpstan/extension-installer/issues",
- "source": "https://github.com/phpstan/extension-installer/tree/1.4.3"
+ "docs": "https://phpstan.org/user-guide/getting-started",
+ "forum": "https://github.com/phpstan/phpstan/discussions",
+ "issues": "https://github.com/phpstan/phpstan/issues",
+ "security": "https://github.com/phpstan/phpstan/security/policy",
+ "source": "https://github.com/phpstan/phpstan-src"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/phpstan",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-09T09:30:48+00:00"
+ },
+ {
+ "name": "phpstan/phpstan-deprecation-rules",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
+ "reference": "1cc1259cb91ee4cfbb5c39bca9f635f067c910b4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/1cc1259cb91ee4cfbb5c39bca9f635f067c910b4",
+ "reference": "1cc1259cb91ee4cfbb5c39bca9f635f067c910b4",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "phpstan/phpstan": "^2.0"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "rules.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
+ "support": {
+ "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues",
+ "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.1"
+ },
+ "time": "2024-11-28T21:56:36+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "11.0.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7",
+ "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^5.4.0",
+ "php": ">=8.2",
+ "phpunit/php-file-iterator": "^5.1.0",
+ "phpunit/php-text-template": "^4.0.1",
+ "sebastian/code-unit-reverse-lookup": "^4.0.1",
+ "sebastian/complexity": "^4.0.1",
+ "sebastian/environment": "^7.2.0",
+ "sebastian/lines-of-code": "^3.0.1",
+ "sebastian/version": "^5.0.2",
+ "theseer/tokenizer": "^1.2.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5.2"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-25T13:26:39+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6",
+ "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-08-27T05:02:59+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "5.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:07:44+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:08:43+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "7.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:09:35+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "11.5.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "9d6046153c2893b521784069e6b5249ce7d2acae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9d6046153c2893b521784069e6b5249ce7d2acae",
+ "reference": "9d6046153c2893b521784069e6b5249ce7d2acae",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.13.0",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.2",
+ "phpunit/php-code-coverage": "^11.0.9",
+ "phpunit/php-file-iterator": "^5.1.0",
+ "phpunit/php-invoker": "^5.0.1",
+ "phpunit/php-text-template": "^4.0.1",
+ "phpunit/php-timer": "^7.0.1",
+ "sebastian/cli-parser": "^3.0.2",
+ "sebastian/code-unit": "^3.0.3",
+ "sebastian/comparator": "^6.3.1",
+ "sebastian/diff": "^6.0.2",
+ "sebastian/environment": "^7.2.0",
+ "sebastian/exporter": "^6.3.0",
+ "sebastian/global-state": "^7.0.2",
+ "sebastian/object-enumerator": "^6.0.1",
+ "sebastian/type": "^5.1.2",
+ "sebastian/version": "^5.0.2",
+ "staabm/side-effects-detector": "^1.0.5"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.14"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-03-19T13:45:48+00:00"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "time": "2023-09-23T14:17:50+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "rector/rector",
+ "version": "2.0.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/rectorphp/rector.git",
+ "reference": "5844a718acb40f40afcd110394270afa55509fd0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/rectorphp/rector/zipball/5844a718acb40f40afcd110394270afa55509fd0",
+ "reference": "5844a718acb40f40afcd110394270afa55509fd0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0",
+ "phpstan/phpstan": "^2.1.6"
+ },
+ "conflict": {
+ "rector/rector-doctrine": "*",
+ "rector/rector-downgrade-php": "*",
+ "rector/rector-phpunit": "*",
+ "rector/rector-symfony": "*"
+ },
+ "suggest": {
+ "ext-dom": "To manipulate phpunit.xml via the custom-rule command"
+ },
+ "bin": [
+ "bin/rector"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Instant Upgrade and Automated Refactoring of any PHP code",
+ "keywords": [
+ "automation",
+ "dev",
+ "migration",
+ "refactoring"
+ ],
+ "support": {
+ "issues": "https://github.com/rectorphp/rector/issues",
+ "source": "https://github.com/rectorphp/rector/tree/2.0.10"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/tomasvotruba",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-03T17:35:18+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:41:36+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-19T07:56:08+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:45:54+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "6.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959",
+ "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/diff": "^6.0",
+ "sebastian/exporter": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.4"
+ },
+ "suggest": {
+ "ext-bcmath": "For comparing BcMath\\Number objects"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-07T06:57:01+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:49:50+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "6.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:53:05+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "7.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5",
+ "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:54:44+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "6.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3",
+ "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-12-05T09:17:50+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "7.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:57:36+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:58:38+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "6.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:00:13+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1"
},
- "time": "2024-09-04T20:21:43+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:01:32+00:00"
},
{
- "name": "phpstan/phpstan",
- "version": "2.1.6",
+ "name": "sebastian/recursion-context",
+ "version": "6.0.2",
"source": {
"type": "git",
- "url": "https://github.com/phpstan/phpstan.git",
- "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c"
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "694d156164372abbd149a4b85ccda2e4670c0e16"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c",
- "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16",
+ "reference": "694d156164372abbd149a4b85ccda2e4670c0e16",
"shasum": ""
},
"require": {
- "php": "^7.4|^8.0"
+ "php": ">=8.2"
},
- "conflict": {
- "phpstan/phpstan-shim": "*"
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
},
- "bin": [
- "phpstan",
- "phpstan.phar"
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:10:34+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "5.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e",
+ "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "security": "https://github.com/sebastianbergmann/type/security/policy",
+ "source": "https://github.com/sebastianbergmann/type/tree/5.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
],
+ "time": "2025-03-18T13:35:50+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "5.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
"autoload": {
- "files": [
- "bootstrap.php"
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "security": "https://github.com/sebastianbergmann/version/security/policy",
+ "source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-09T05:16:32+00:00"
+ },
+ {
+ "name": "staabm/side-effects-detector",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/staabm/side-effects-detector.git",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.6",
+ "phpunit/phpunit": "^9.6.21",
+ "symfony/var-dumper": "^5.4.43",
+ "tomasvotruba/type-coverage": "1.0.0",
+ "tomasvotruba/unused-public": "1.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "lib/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "PHPStan - PHP Static Analysis Tool",
+ "description": "A static analysis tool to detect side effects in PHP code",
"keywords": [
- "dev",
"static analysis"
],
"support": {
- "docs": "https://phpstan.org/user-guide/getting-started",
- "forum": "https://github.com/phpstan/phpstan/discussions",
- "issues": "https://github.com/phpstan/phpstan/issues",
- "security": "https://github.com/phpstan/phpstan/security/policy",
- "source": "https://github.com/phpstan/phpstan-src"
+ "issues": "https://github.com/staabm/side-effects-detector/issues",
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
},
"funding": [
{
- "url": "https://github.com/ondrejmirtes",
+ "url": "https://github.com/staabm",
"type": "github"
+ }
+ ],
+ "time": "2024-10-20T05:08:20+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
- "url": "https://github.com/phpstan",
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2025-02-19T15:46:42+00:00"
+ "time": "2024-09-25T14:20:29+00:00"
},
{
- "name": "rector/rector",
- "version": "2.0.9",
+ "name": "symfony/var-dumper",
+ "version": "v7.2.3",
"source": {
"type": "git",
- "url": "https://github.com/rectorphp/rector.git",
- "reference": "4393230e478c0006795770fe74c223b5c64ed68c"
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "82b478c69745d8878eb60f9a049a4d584996f73a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/rectorphp/rector/zipball/4393230e478c0006795770fe74c223b5c64ed68c",
- "reference": "4393230e478c0006795770fe74c223b5c64ed68c",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a",
+ "reference": "82b478c69745d8878eb60f9a049a4d584996f73a",
"shasum": ""
},
"require": {
- "php": "^7.4|^8.0",
- "phpstan/phpstan": "^2.1.3"
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "rector/rector-doctrine": "*",
- "rector/rector-downgrade-php": "*",
- "rector/rector-phpunit": "*",
- "rector/rector-symfony": "*"
+ "symfony/console": "<6.4"
},
- "suggest": {
- "ext-dom": "To manipulate phpunit.xml via the custom-rule command"
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0",
+ "twig/twig": "^3.12"
},
"bin": [
- "bin/rector"
+ "Resources/bin/var-dump-server"
],
"type": "library",
"autoload": {
"files": [
- "bootstrap.php"
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "Instant Upgrade and Automated Refactoring of any PHP code",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
"keywords": [
- "automation",
- "dev",
- "migration",
- "refactoring"
+ "debug",
+ "dump"
],
"support": {
- "issues": "https://github.com/rectorphp/rector/issues",
- "source": "https://github.com/rectorphp/rector/tree/2.0.9"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.2.3"
},
"funding": [
{
- "url": "https://github.com/tomasvotruba",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-17T11:39:41+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
"type": "github"
}
],
- "time": "2025-02-10T08:14:01+00:00"
+ "time": "2024-03-03T12:36:25+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^8.2",
"ext-json": "*"
},
- "platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
}
diff --git a/content/v3/de/awesome-plugins/apm.md b/content/v3/de/awesome-plugins/apm.md
new file mode 100644
index 0000000..48763f6
--- /dev/null
+++ b/content/v3/de/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM Dokumentation
+
+Willkommen in FlightPHP APM—der persönliche Leistungstrainer deiner App! Dieser Leitfaden ist deine Roadmap zum Einrichten, Verwenden und Meistern des Application Performance Monitoring (APM) mit FlightPHP. Egal, ob du langsame Anfragen aufspürst oder einfach nur die Latenzdiagramme bewundern möchtest, wir haben dich abgedeckt. Lass uns deine App schneller, deine Benutzer glücklicher und deine Debugging-Sitzungen zum Kinderspiel machen!
+
+## Warum APM wichtig ist
+
+Stell dir Folgendes vor: Deine App ist ein geschäftiges Restaurant. Ohne eine Möglichkeit, die Dauer von Bestellungen zu verfolgen oder wo die Küche ins Stocken gerät, rätst du, warum Kunden verärgert gehen. APM ist dein Sous-Chef—er beobachtet jeden Schritt, von eingehenden Anfragen bis zu Datenbankabfragen, und markiert alles, was dich verlangsamt. Langsame Seiten verlieren Benutzer (Studien zeigen, dass 53% abspringen, wenn eine Seite über 3 Sekunden zum Laden benötigt!), und APM hilft dir, diese Probleme *bevor* sie schmerzhaft werden. Es ist proaktive Gelassenheit—weniger „warum ist das kaputt?“ Momente, mehr „schau, wie reibungslos das läuft!“ Gewinne.
+
+## Installation
+
+Starte mit Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Du benötigst:
+- **PHP 7.4+**: Hält uns kompatibel mit LTS Linux-Distributionen und unterstützt modernes PHP.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Das leichte Framework, das wir verstärken.
+
+## Erste Schritte
+
+Hier ist deine Schritt-für-Schritt-Anleitung zur APM-Tollheit:
+
+### 1. Registriere das APM
+
+Füge dies in deine `index.php` oder eine `services.php` Datei ein, um das Tracking zu starten:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Was passiert hier?**
+- `LoggerFactory::create()` erfasst deine Konfiguration (mehr dazu bald) und richtet einen Logger ein—SQLite standardmäßig.
+- `Apm` ist der Star—er hört auf die Events von Flight (Anfragen, Routen, Fehler usw.) und sammelt Kennzahlen.
+- `bindEventsToFlightInstance($app)` verknüpft alles mit deiner Flight-App.
+
+**Pro-Tipp: Sampling**
+Wenn deine App beschäftigt ist, könnte das Protokollieren *jeder* Anfrage die Dinge überlasten. Verwende eine Stichprobenrate (0.0 bis 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Protokolliert 10% der Anfragen
+```
+
+Dies hält die Leistung schnell, während es dir dennoch solide Daten gibt.
+
+### 2. Konfiguriere es
+
+Führe dies aus, um deine `.runway-config.json` zu erstellen:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Was macht das?**
+- Startet einen Assistenten, der fragt, woher die Rohdaten kommen (Quelle) und wohin die verarbeiteten Daten gehen (Ziel).
+- Standard ist SQLite—z.B. `sqlite:/tmp/apm_metrics.sqlite` für die Quelle, ein anderes für das Ziel.
+- Du wirst mit einer Konfiguration wie dieser enden:
+ ```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"
+ }
+ }
+ ```
+
+**Warum zwei Standorte?**
+Rohdaten häufen sich schnell an (denk an ungefilterte Protokolle). Der Worker verarbeitet sie in ein strukturiertes Ziel für das Dashboard. Hält die Dinge ordentlich!
+
+### 3. Verarbeite Kennzahlen mit dem Worker
+
+Der Worker verwandelt Rohdaten in dashboard-bereite Daten. Führe 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 Kennzahlen (standardmäßige Batchgröße) in dein Ziel.
+- Stoppt, wenn er fertig ist oder wenn keine Kennzahlen mehr vorhanden sind.
+
+**Lass ihn laufen**
+Für Live-Apps möchtest du kontinuierliche Verarbeitung. Hier sind deine Optionen:
+
+- **Daemon-Modus**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Läuft für immer, verarbeitet Kennzahlen, sobald sie eintreffen. Großartig für Entwicklungs- oder kleine Setups.
+
+- **Crontab**:
+ Füge dies zu deiner Crontab hinzu (`crontab -e`):
+ ```bash
+ * * * * * php /path/to/project/vendor/bin/runway apm:worker
+ ```
+ Läuft jede Minute—perfekt für die Produktion.
+
+- **Tmux/Screen**:
+ Starte eine abtrennbare Sitzung:
+ ```bash
+ tmux new -s apm-worker
+ php vendor/bin/runway apm:worker --daemon
+ # Ctrl+B, dann D um zu trennen; `tmux attach -t apm-worker` um wieder zu verbinden
+ ```
+ Hält es am Laufen, auch wenn du dich abmeldest.
+
+- **Benutzerdefinierte Anpassungen**:
+ ```bash
+ php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
+ ```
+ - `--batch_size 50`: Verarbeite 50 Kennzahlen gleichzeitig.
+ - `--max_messages 1000`: Stoppe nach 1000 Kennzahlen.
+ - `--timeout 300`: Beende nach 5 Minuten.
+
+**Warum sich die Mühe machen?**
+Ohne den Worker ist dein Dashboard leer. Es ist die Brücke zwischen Rohprotokollen und umsetzbaren Erkenntnissen.
+
+### 4. Starte das Dashboard
+
+Sieh die Vitalwerte deiner App:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**Was ist das?**
+- Startet einen PHP-Server bei `http://localhost:8001/apm/dashboard`.
+- Zeigt Anfragenprotokolle, langsame Routen, Fehlerquoten und mehr an.
+
+**Passe es an**:
+```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 erreichbar (praktisch für die Fernansicht).
+- `--port 8080`: Verwende einen anderen Port, falls 8001 belegt ist.
+- `--php-path`: Verweise auf PHP, wenn es nicht in deinem PATH ist.
+
+Rufe die URL in deinem Browser auf und erkunde!
+
+#### Produktionsmodus
+
+Für die Produktion musst du vielleicht ein paar Techniken ausprobieren, um das Dashboard zum Laufen zu bringen, da wahrscheinlich Firewalls und andere Sicherheitsmaßnahmen vorhanden sind. Hier sind einige Optionen:
+
+- **Verwende einen Reverse Proxy**: Richte Nginx oder Apache ein, um Anfragen an das Dashboard weiterzuleiten.
+- **SSH-Tunnel**: Wenn du auf den Server SSH haben kannst, benutze `ssh -L 8080:localhost:8001 youruser@yourserver`, um das Dashboard zu deinem lokalen Rechner zu tunneln.
+- **VPN**: Wenn dein Server hinter einem VPN ist, verbinde dich damit und greife direkt auf das Dashboard zu.
+- **Firewall konfigurieren**: Öffne den Port 8001 für deine IP oder das Netzwerk des Servers. (oder welchen Port du auch immer eingestellt hast).
+- **Apache/Nginx konfigurieren**: Wenn du einen Webserver vor deiner Anwendung hast, kannst du ihn auf eine Domain oder Subdomain konfigurieren. Wenn du dies tust, legst du das Dokumentenstammverzeichnis auf `/path/to/your/project/vendor/flightphp/apm/dashboard`.
+
+#### Möchtest du ein anderes Dashboard?
+
+Du kannst auch dein eigenes Dashboard erstellen, wenn du möchtest! Schau dir das Verzeichnis vendor/flightphp/apm/src/apm/presenter an, um Ideen zu sammeln, wie du die Daten für dein eigenes Dashboard präsentieren kannst!
+
+## Dashboard-Funktionen
+
+Das Dashboard ist dein APM-HQ—hier ist, was du sehen wirst:
+
+- **Anfrageprotokoll**: Jede Anfrage mit Timestamp, URL, Antwort-Code und Gesamtzeit. Klicke auf „Details“ für Middleware, Abfragen und Fehler.
+- **Langsamste Anfragen**: Die Top 5 Anfragen, die Zeit beanspruchen (z.B. „/api/heavy“ mit 2,5s).
+- **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-Perzentile**: 95. (p95) und 99. (p99) Antwortzeiten—kenne deine schlimmsten Szenarien.
+- **Antwortcode-Diagramm**: Visualisiere 200er, 404er, 500er über die Zeit.
+- **Lange Abfragen/Middleware**: Die Top 5 langsamen Datenbankaufrufe und Middleware-Schichten.
+- **Cache-Hit/Fehl**: Wie oft dein Cache den Tag rettet.
+
+**Extras**:
+- Filter nach „Letzte Stunde“, „Letzter Tag“ oder „Letzte Woche“.
+- Schalte den Dunkelmodus für späte Nächte ein.
+
+**Beispiel**:
+Eine Anfrage an `/users` könnte folgendes anzeigen:
+- Gesamtzeit: 150ms
+- Middleware: `AuthMiddleware->handle` (50ms)
+- Abfrage: `SELECT * FROM users` (80ms)
+- Cache: Treffer bei `user_list` (5ms)
+
+## Hinzufügen benutzerdefinierter Ereignisse
+
+Verfolge alles—wie einen API-Aufruf oder einen Zahlungsprozess:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Wo erscheint das?**
+Im Dashboard unter den Anfragedetails unter „Benutzerdefinierte Ereignisse“—erweiterbar mit ansprechender JSON-Formatierung.
+
+**Anwendungsfall**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Jetzt siehst du, ob diese API deine App ausbremst!
+
+## Datenbanküberwachung
+
+Verfolge PDO-Abfragen wie folgt:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Was du bekommst**:
+- Abfragetext (z.B. `SELECT * FROM users WHERE id = ?`)
+- Ausführungszeit (z.B. 0.015s)
+- Zeilenzahl (z.B. 42)
+
+**Hinweis**:
+- **Optional**: Überspringe dies, wenn du kein DB-Tracking benötigst.
+- **Nur PdoWrapper**: Core PDO ist noch nicht verbunden—bleib dran!
+- **Leistungswarnung**: Das Protokollieren jeder Abfrage auf einer DB-intensiven Seite kann die Dinge verlangsamen. Verwende Sampling (`$Apm = new Apm($ApmLogger, 0.1)`), um die Last zu verringern.
+
+**Beispielausgabe**:
+- Abfrage: `SELECT name FROM products WHERE price > 100`
+- Zeit: 0.023s
+- Zeilen: 15
+
+## Worker-Optionen
+
+Stimme den Worker nach deinen Wünschen ab:
+
+- `--timeout 300`: Stoppt nach 5 Minuten—gut für Tests.
+- `--max_messages 500`: Begrenzt auf 500 Kennzahlen—hält es endlich.
+- `--batch_size 200`: Verarbeitet 200 auf einmal—balanciert Geschwindigkeit und Speicher.
+- `--daemon`: Läuft nonstop—ideal für die Live-Überwachung.
+
+**Beispiel**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+Läuft eine Stunde, verarbeitet 100 Kennzahlen gleichzeitig.
+
+## Fehlersuche
+
+Steck fest? Probiere diese:
+
+- **Keine Dashboard-Daten?**
+ - Läuft der Worker? Überprüfe `ps aux | grep apm:worker`.
+ - Stimmt der Konfigurationspfad? Verifiziere, dass die `.runway-config.json` DSNs auf echte Dateien zeigen.
+ - Führe `php vendor/bin/runway apm:worker` manuell aus, um ausstehende Kennzahlen zu verarbeiten.
+
+- **Worker-Fehler?**
+ - Schau dir deine SQLite-Dateien an (z.B. `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`).
+ - Überprüfe die PHP-Protokolle auf Stack-Traces.
+
+- **Dashboard lässt sich nicht starten?**
+ - Port 8001 in Gebrauch? Verwende `--port 8080`.
+ - PHP nicht gefunden? Verwende `--php-path /usr/bin/php`.
+ - Firewall blockiert? Öffne den Port oder verwende `--host localhost`.
+
+- **Zu langsam?**
+ - Senke die Stichprobenrate: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Reduziere die Batch-Größe: `--batch_size 20`.
\ 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 39560b1..6948a2d 100644
--- a/content/v3/de/awesome-plugins/awesome_plugins.md
+++ b/content/v3/de/awesome-plugins/awesome_plugins.md
@@ -1,35 +1,40 @@
-# Tolle Plugins
+# Fantastische Plugins
-Flight ist unglaublich erweiterbar. Es gibt eine Reihe von Plugins, die verwendet werden können, um Funktionen zu Ihrer Flight-Anwendung hinzuzufügen. Einige werden offiziell vom Flight-Team unterstützt und andere sind Mikro-/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 Mikro-/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 im Gegenzug erwarten können. Es stehen einige Tools zur Verfügung, um Ihnen zu helfen, API-Dokumentation für Ihre Flight-Projekte zu erstellen.
+API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie im Gegenzug erwarten können. Es gibt einige Tools, die Ihnen helfen, die 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 zu erstellen.
-- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um Ihnen zu helfen, API-Dokumentation für Ihre Flight-Projekte zu erstellen. 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 erstellen.
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentationen 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)
+
+Anwendungsleistungsüberwachung (APM) ist entscheidend für jede Anwendung. Sie hilft Ihnen zu verstehen, wie Ihre Anwendung funktioniert und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können.
+- beta[flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann genutzt werden, um die Leistung Ihrer Anwendung zu überwachen und Engpässe zu identifizieren.
## Authentifizierung/Autorisierung
-Authentifizierung und Autorisierung sind entscheidend für jede Anwendung, die Kontrollen darüber verlangt, wer auf was zugreifen kann.
+Authentifizierung und Autorisierung sind entscheidend für jede Anwendung, die Kontrollen benötigt, um festzulegen, wer auf was zugreifen kann.
-- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight-Berechtigungsbibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsberechtigungen 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.
## 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-Datei-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.
+CLI-Anwendungen sind eine großartige Möglichkeit, mit Ihrer Anwendung zu interagieren. Sie können verwendet werden, 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
-Cookies sind eine großartige Möglichkeit, kleine Datenelemente auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzereinstellungen, Anwendungsoptionen 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 Benutzervoreinstellungen, 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.
@@ -37,43 +42,43 @@ Cookies sind eine großartige Möglichkeit, kleine Datenelemente auf der Client-
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 funktionsreicher Fehlerhandler, der mit Flight verwendet werden kann. Es gibt mehrere Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach, es zu erweitern und Ihre eigenen Panels hinzuzufügen.
-- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerhandler verwendet, fügt dieses Plugin einige zusätzliche Panels hinzu, um insbesondere für Flight-Projekte beim Debuggen zu helfen.
+- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein voll funktionsfähiger Fehlerhandler, der mit Flight verwendet werden kann. Er hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist außerdem sehr einfach zu erweitern und eigene Panels hinzuzufügen.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerhandler verwendet, dieses Plugin fügt einige zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern.
## Datenbanken
-Datenbanken sind der Kern der meisten Anwendungen. So speichern und holen Sie Daten. Einige Datenbankbibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs.
+Datenbanken sind das Herz der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbankbibliotheken sind einfach Wrapper zum Schreiben von Abfragen, während andere vollwertige ORMs sind.
-- offiziell [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Offizieller Flight PDO Wrapper, der Teil des Kerns ist. Dies ist ein einfacher Wrapper, um den Prozess des Schreibens von Abfragen und deren Ausführung zu vereinfachen. Es ist kein ORM.
-- offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Großartige kleine Bibliothek zum einfachen Abrufen und Speichern von Daten in Ihrer Datenbank.
+- official [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Offizieller Flight PDO Wrapper, der Teil des Kern ist. Dies ist ein einfacher Wrapper, um den Prozess des Schreibens von Abfragen und deren Ausführung zu erleichtern. Es ist kein ORM.
+- official [flightphp/active-record](/awesome-plugins/active-record) - Offizieller Flight ActiveRecord ORM/Mapper. Großartige kleine Bibliothek für das einfache Abrufen und Speichern von Daten in Ihrer Datenbank.
- [byjg/php-migration](/awesome-plugins/migrations) - Plugin zur Verfolgung aller Datenbankänderungen für Ihr Projekt.
## Verschlüsselung
-Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Die Daten zu verschlüsseln und zu entschlüsseln ist nicht allzu schwer, aber das korrekte 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.) [schwierig](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sein](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 Ihrem Code-Repository zu committen.
+Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Die Verschlüsselung und Entschlüsselung der Daten ist nicht allzu schwierig, aber den Schlüssel zur Verschlüsselung richtig zu speichern [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.) [schwierig](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sein](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 einzuchecken.
-- [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Es ist ziemlich einfach, loszulegen und mit der Verschlüsselung und Entschlüsselung von Daten zu beginnen.
+- [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 recht einfach, um mit der Verschlüsselung und Entschlüsselung von Daten zu beginnen.
-## Job-Warteschlange
+## Job-Queue
-Job-Warteschlangen sind sehr hilfreich, um Aufgaben asynchron zu verarbeiten. Dies kann das Versenden von E-Mails, das Verarbeiten von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss.
+Job-Queues sind sehr hilfreich, um Aufgaben asynchron zu verarbeiten. Dies kann das Versenden von E-Mails, die Verarbeitung von Bildern oder alles, was nicht in Echtzeit erledigt werden muss, sein.
- [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.
## Sitzung
-Sitzungen sind für APIs nicht wirklich nützlich, aber für den Aufbau einer Webanwendung können Sitzungen entscheidend sein, um den Status und die Anmeldeinformationen aufrechtzuerhalten.
+Sitzungen sind für APIs nicht wirklich nützlich, aber für den Aufbau einer Webanwendung können Sitzungen entscheidend sein, um den Zustand und die Anmeldeinformationen zu erhalten.
-- offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight-Sitzungsbibliothek. Dies ist eine einfache Sitzungsbibliothek, die verwendet werden kann, um Sitzungsdaten zu speichern und abzurufen. Sie verwendet die integrierte Sitzungsverwaltung von PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht blockierend, Flash, Segment, Sitzungsverschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Sitzungsdaten.
+- official [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Sitzungsbibliothek, die verwendet werden kann, um Sitzungsdaten zu speichern und abzurufen. Sie verwendet die integrierte Sitzungsverwaltung von PHP.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht-blockierend, Flash, Segment, Sitzungsverschlüsselung). Verwendet PHP open_ssl für die optionale Verschlüsselung/Entschlüsselung von Sitzungsdaten.
-## Vorlagen
+## Vorlagenverarbeitung
-Vorlagen sind der Kern jeder Webanwendung mit einer UI. Es gibt eine Reihe von Template-Engines, die mit Flight verwendet werden können.
+Vorlagenverarbeitung ist grundlegend für jede Webanwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Vorlagenmotoren, die mit Flight verwendet werden können.
-- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr einfache Template-Engine, die Teil des Kerns ist. 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 Template-Engine, die sehr einfach zu bedienen ist und sich näher an einer PHP-Syntax als an Twig oder Smarty anfühlt. Es ist auch sehr einfach, es zu erweitern und eigene Filter und Funktionen hinzuzufügen.
+- deprecated [flightphp/core View](/learn#views) - Dies ist ein sehr einfacher Vorlagenmotor, der Teil des Kern ist. Es wird nicht empfohlen, ihn zu verwenden, wenn Sie mehr als ein paar Seiten in Ihrem Projekt haben.
+- [latte/latte](/awesome-plugins/latte) - Latte ist ein voll funktionsfähiger Vorlagenmotor, der sehr einfach zu verwenden ist und sich näher an einer PHP-Syntax anfühlt als Twig oder Smarty. Es ist auch sehr einfach, eigene Filter und Funktionen hinzuzufügen.
## Mitwirken
-Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie eine Pull-Anfrage ein, um es zur Liste hinzuzufügen!
\ No newline at end of file
+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/tracy_extensions.md b/content/v3/de/awesome-plugins/tracy_extensions.md
index 2747dc5..16b3823 100644
--- a/content/v3/de/awesome-plugins/tracy_extensions.md
+++ b/content/v3/de/awesome-plugins/tracy_extensions.md
@@ -1,32 +1,32 @@
Tracy Flight Panel Erweiterungen
=====
-Dies ist eine Sammlung von Erweiterungen, um die Arbeit mit Flight etwas komfortabler zu gestalten.
+Dies ist eine Sammlung von Erweiterungen, um die Arbeit mit Flight ein wenig reicher zu gestalten.
- Flight - Analysiere alle Flight-Variablen.
-- Datenbank - Analysiere alle Abfragen auf der Seite (wenn Sie die Datenbankverbindung korrekt initialisieren)
+- Datenbank - Analysiere alle Abfragen, die auf der Seite ausgeführt wurden (wenn du die Datenbankverbindung korrekt initiierst)
- Anfrage - Analysiere alle `$_SERVER`-Variablen und untersuche alle globalen Payloads (`$_GET`, `$_POST`, `$_FILES`)
- Sitzung - Analysiere alle `$_SESSION`-Variablen, wenn Sitzungen aktiv sind.
Dies ist das Panel
-
+
-Und jedes Panel zeigt sehr hilfreiche Informationen über Ihre Anwendung!
+Und jedes Panel zeigt sehr hilfreiche Informationen über deine Anwendung an!
-
-
-
+
+
+
-Klicke [hier](https://github.com/flightphp/tracy-extensions), um den Code anzusehen.
+Klicke [hier](https://github.com/flightphp/tracy-extensions), um den Code zu sehen.
Installation
-------
-Führen Sie `composer require flightphp/tracy-extensions --dev` aus und los geht's!
+Führe `composer require flightphp/tracy-extensions --dev` aus und du bist auf dem Weg!
Konfiguration
-------
-Es gibt sehr wenig Konfiguration, die Sie benötigen, um dies zu starten. Sie müssen den Tracy-Debugger initialisieren, bevor Sie dies verwenden [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Es gibt sehr wenig Konfiguration, die du machen musst, um dies zu starten. Du musst den Tracy-Debugger initiieren, bevor du dies verwendest [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // Dies muss falsch sein, oder Tracy kann tatsächlich nicht gerendert werden :(
+ // Dies muss falsch sein oder Tracy kann es nicht tatsächlich rendern :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -88,7 +89,7 @@ Flight::start();
### Latte
-Wenn Sie Latte in Ihrem Projekt installiert haben, können Sie das Latte-Panel verwenden, um Ihre Vorlagen zu analysieren. Sie können die Latte-Instanz an den `TracyExtensionLoader`-Konstruktor mit dem `latte`-Schlüssel im zweiten Parameter übergeben.
+Wenn du Latte in deinem Projekt installiert hast, kannst du das Latte-Panel verwenden, um deine Vorlagen zu analysieren. Du kannst die Latte-Instanz im Konstruktor von `TracyExtensionLoader` mit dem Schlüssel `latte` im zweiten Parameter übergeben.
```php
@@ -101,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // Hier fügen Sie das Latte Panel zu Tracy hinzu
+ // hier fügst du das Latte-Panel zu Tracy hinzu
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // Dies muss falsch sein, oder Tracy kann tatsächlich nicht gerendert werden :(
+ // Dies muss falsch sein oder Tracy kann es nicht tatsächlich rendern :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/de/learn/events.md b/content/v3/de/learn/events.md
index 74ffd62..8f1c075 100644
--- a/content/v3/de/learn/events.md
+++ b/content/v3/de/learn/events.md
@@ -1,41 +1,41 @@
# Ereignissystem in Flight PHP (v3.15.0+)
-Flight PHP führt ein leichtgewichtiges und intuitives Ereignissystem ein, mit dem Sie benutzerdefinierte Ereignisse in Ihrer Anwendung registrieren und auslösen können. Mit der Ergänzung von `Flight::onEvent()` und `Flight::triggerEvent()` können Sie nun in Schlüsselereignisse im Lebenszyklus Ihrer App eintauchen oder Ihre eigenen Ereignisse definieren, um Ihren Code modularer und erweiterbarer zu gestalten. Diese Methoden sind Teil von Flight's **mapbaren Methoden**, was bedeutet, dass Sie deren Verhalten nach Ihren Bedürfnissen anpassen können.
+Flight PHP führt ein leichtgewichtiges und intuitives Ereignissystem ein, mit dem Sie benutzerdefinierte Ereignisse in Ihrer Anwendung registrieren und auslösen können. Mit der Hinzufügung von `Flight::onEvent()` und `Flight::triggerEvent()` können Sie jetzt in wichtige Momente des Lebenszyklus Ihrer App eingreifen oder eigene Ereignisse definieren, um Ihren Code modularer und erweiterbar zu gestalten. Diese Methoden sind Teil von Flight's **mappable methods**, was bedeutet, dass Sie ihr Verhalten an Ihre Bedürfnisse anpassen können.
-Dieser Leitfaden behandelt alles, was Sie wissen müssen, um mit Ereignissen zu beginnen, einschließlich ihrer Wertigkeit, ihrer Nutzung und praktischer Beispiele, um Anfängern ihre Leistungsfähigkeit zu verdeutlichen.
+Dieser Leitfaden behandelt alles, was Sie wissen müssen, um mit Ereignissen zu beginnen, einschließlich warum sie wertvoll sind, wie man sie verwendet und praktische Beispiele, um Anfängern ihre Stärke näherzubringen.
## Warum Ereignisse verwenden?
-Ereignisse ermöglichen es Ihnen, verschiedene Teile Ihrer Anwendung zu trennen, sodass sie nicht zu stark voneinander abhängen. Diese Trennung—oft als **Entkopplung** bezeichnet—macht es einfacher, Ihren Code zu aktualisieren, zu erweitern oder zu debuggen. Anstatt alles in einem großen Block zu schreiben, können Sie Ihre Logik in kleinere, unabhängige Teile aufteilen, die auf spezifische Aktionen (Ereignisse) reagieren.
+Ereignisse ermöglichen es Ihnen, verschiedene Teile Ihrer Anwendung zu trennen, sodass sie nicht zu stark voneinander abhängen. Diese Trennung—oft als **Entkopplung** bezeichnet—macht Ihren Code einfacher zu aktualisieren, zu erweitern oder zu debuggen. Anstatt alles in einem großen Stück zu schreiben, können Sie Ihre Logik in kleinere, unabhängige Teile aufteilen, die auf spezifische Aktionen (Ereignisse) reagieren.
Stellen Sie sich vor, Sie bauen eine Blog-App:
-- Wenn ein Benutzer einen Kommentar veröffentlicht, möchten Sie möglicherweise:
+- Wenn ein Benutzer einen Kommentar postet, möchten Sie vielleicht:
- Den Kommentar in der Datenbank speichern.
- - Eine E-Mail an den Blog-Besitzer senden.
+ - Eine E-Mail an den Blogbesitzer senden.
- Die Aktion aus Sicherheitsgründen protokollieren.
-Ohne Ereignisse würden Sie das alles in eine Funktion quetschen. Mit Ereignissen können Sie es aufteilen: Ein Teil speichert den Kommentar, ein anderer löst ein Ereignis wie `'comment.posted'` aus, und separate Listener kümmern sich um die E-Mail und das Protokollieren. Dadurch bleibt Ihr Code sauberer und Sie können Funktionen (wie Benachrichtigungen) hinzufügen oder entfernen, ohne die Kernlogik zu berühren.
+Ohne Ereignisse würden Sie all dies in eine Funktion quetschen. Mit Ereignissen können Sie es aufteilen: Ein Teil speichert den Kommentar, ein anderer löst ein Ereignis wie `'comment.posted'` aus, und separate Listener übernehmen die E-Mail und das Protokollieren. Dies hält Ihren Code sauberer und ermöglicht es Ihnen, Funktionen (wie Benachrichtigungen) hinzuzufügen oder zu entfernen, ohne die Kernlogik anzufassen.
-### Häufige Anwendungen
+### Häufige Verwendungen
- **Protokollierung**: Aktionen wie Anmeldungen oder Fehler protokollieren, ohne Ihren Hauptcode zu überladen.
-- **Benachrichtigungen**: E-Mails oder Alarme senden, wenn etwas passiert.
-- **Updates**: Caches aktualisieren oder andere Systeme über Änderungen informieren.
+- **Benachrichtigungen**: E-Mails oder Warnungen senden, wenn etwas passiert.
+- **Aktualisierungen**: Caches aktualisieren oder andere Systeme über Änderungen informieren.
## Registrieren von Ereignis-Listenern
-Um auf ein Ereignis zu hören, verwenden Sie `Flight::onEvent()`. Diese Methode ermöglicht es Ihnen zu definieren, was passieren soll, wenn ein Ereignis eintritt.
+Um auf ein Ereignis zu hören, verwenden Sie `Flight::onEvent()`. Diese Methode ermöglicht es Ihnen, festzulegen, was passieren soll, wenn ein Ereignis auftritt.
### Syntax
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Ein Name für Ihr Ereignis (z.B. `'user.login'`).
-- `$callback`: Die Funktion, die ausgeführt wird, wenn das Ereignis ausgelöst wird.
+- `$event`: Ein Name für Ihr Ereignis (z. B. `'user.login'`).
+- `$callback`: Die Funktion, die ausgeführt werden soll, wenn das Ereignis ausgelöst wird.
### Wie es funktioniert
-Sie "abonnieren" ein Ereignis, indem Sie Flight mitteilen, was zu tun ist, wenn es eintritt. Der Callback kann Argumente akzeptieren, die vom Ereignisauslöser übergeben werden.
+Sie "abonnieren" ein Ereignis, indem Sie Flight mitteilen, was zu tun ist, wenn es eintritt. Der Callback kann Argumente akzeptieren, die vom Ereignis-Trigger übergeben werden.
-Das Ereignissystem von Flight ist synchron, was bedeutet, dass jeder Ereignis-Listener nacheinander ausgeführt wird, einer nach dem anderen. Wenn Sie ein Ereignis auslösen, laufen alle registrierten Listener für dieses Ereignis bis zur Vollständigkeit, bevor Ihr Code fortfährt. Dies ist wichtig zu verstehen, da es sich von asynchronen Ereignissystemen unterscheidet, bei denen Listener parallel oder zu einem späteren Zeitpunkt ausgeführt werden können.
+Das Ereignissystem von Flight ist synchron, was bedeutet, dass jeder Ereignis-Listener der Reihe nach ausgeführt wird, einer nach dem anderen. Wenn Sie ein Ereignis auslösen, werden alle registrierten Listener für dieses Ereignis zu Ende ausgeführt, bevor Ihr Code fortgesetzt wird. Dies ist wichtig zu verstehen, da es sich von asynchronen Ereignissystemen unterscheidet, bei denen Listener parallel oder zu einem späteren Zeitpunkt ausgeführt werden könnten.
### Einfaches Beispiel
```php
@@ -43,7 +43,7 @@ Flight::onEvent('user.login', function ($username) {
echo "Willkommen zurück, $username!";
});
```
-Hier wird bei Auslösung des Ereignisses `'user.login'` der Benutzer namentlich begrüßt.
+Hier, wenn das Ereignis `'user.login'` ausgelöst wird, wird der Benutzer namentlich begrüßt.
### Wichtige Punkte
- Sie können mehrere Listener für dasselbe Ereignis hinzufügen—sie werden in der Reihenfolge ausgeführt, in der Sie sie registriert haben.
@@ -51,32 +51,32 @@ Hier wird bei Auslösung des Ereignisses `'user.login'` der Benutzer namentlich
## Auslösen von Ereignissen
-Um ein Ereignis auszulösen, verwenden Sie `Flight::triggerEvent()`. Dies teilt Flight mit, alle für dieses Ereignis registrierten Listener auszuführen und alle Daten, die Sie bereitstellen, weiterzuleiten.
+Um ein Ereignis auszulösen, verwenden Sie `Flight::triggerEvent()`. Dies sagt Flight, dass alle für dieses Ereignis registrierten Listener ausgeführt werden sollen, und dabei alle Daten übergeben werden, die Sie bereitstellen.
### Syntax
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: Der Ereignisname, den Sie auslösen (muss mit einem registrierten Ereignis übereinstimmen).
-- `...$args`: Optionale Argumente, die an die Listener gesendet werden (können beliebig viele Argumente sein).
+- `$event`: Der Name des Ereignisses, das Sie auslösen (muss mit einem registrierten Ereignis übereinstimmen).
+- `...$args`: Optionale Argumente, die an die Listener gesendet werden sollen (kann beliebig viele Argumente sein).
### Einfaches Beispiel
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Dies löst das Ereignis `'user.login'` aus und sendet `'alice'` an den zuvor definierten Listener, der ausgeben wird: `Willkommen zurück, alice!`.
+Dies löst das Ereignis `'user.login'` aus und sendet `'alice'` an den zuvor definierten Listener, der Folgendes ausgeben wird: `Willkommen zurück, alice!`.
### Wichtige Punkte
- Wenn keine Listener registriert sind, passiert nichts—Ihre App wird nicht abstürzen.
-- Verwenden Sie den Spread-Operator (`...`), um flexibel mehrere Argumente zu übergeben.
+- Verwenden Sie den Spread-Operator (`...`), um mehrere Argumente flexibel zu übergeben.
### Registrieren von Ereignis-Listenern
...
**Weitere Listener stoppen**:
-Wenn ein Listener `false` zurückgibt, werden keine zusätzlichen Listener für dieses Ereignis ausgeführt. Dies ermöglicht es Ihnen, die Ereigniskette basierend auf bestimmten Bedingungen zu stoppen. Denken Sie daran, dass die Reihenfolge der Listener wichtig ist, da der erste, der `false` zurückgibt, den Rest am Ausführen hindert.
+Wenn ein Listener `false` zurückgibt, werden keine zusätzlichen Listener für dieses Ereignis ausgeführt. Dies ermöglicht es Ihnen, die Ereigniskette unter bestimmten Bedingungen zu stoppen. Denken Sie daran, die Reihenfolge der Listener ist wichtig, da der erste, der `false` zurückgibt, die Ausführung der restlichen Listener stoppt.
**Beispiel**:
```php
@@ -93,30 +93,30 @@ Flight::onEvent('user.login', function ($username) {
## Überschreiben von Ereignismethoden
-`Flight::onEvent()` und `Flight::triggerEvent()` sind verfügbar, um [erweitert](/learn/extending) zu werden, was bedeutet, dass Sie neu definieren können, wie sie funktionieren. Dies ist großartig für fortgeschrittene Benutzer, die das Ereignissystem anpassen möchten, z.B. durch Hinzufügen von Protokollierung oder Ändern der Art und Weise, wie Ereignisse ausgelöst werden.
+`Flight::onEvent()` und `Flight::triggerEvent()` sind verfügbar, um [erweitert](/learn/extending) zu werden, was bedeutet, dass Sie neu definieren können, wie sie funktionieren. Dies ist großartig für fortgeschrittene Benutzer, die das Ereignissystem anpassen möchten, z. B. um Protokollierung hinzuzufügen oder zu ändern, wie Ereignisse versendet werden.
### Beispiel: Anpassen von `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
// Protokolliere jede Ereignisregistrierung
- error_log("Neuer Ereignis-Listener hinzugefügt für: $event");
- // Rufe das Standardverhalten auf (vorausgesetzt, es gibt ein internes Ereignissystem)
+ error_log("Neuer Ereignislistener hinzugefügt für: $event");
+ // Rufe das Standardverhalten auf (unter der Annahme, dass es ein internes Ereignissystem gibt)
Flight::_onEvent($event, $callback);
});
```
-Jetzt wird jedes Mal, wenn Sie ein Ereignis registrieren, dies protokolliert, bevor es fortfährt.
+Jetzt protokolliert es jedes Mal, wenn Sie ein Ereignis registrieren, bevor es fortfährt.
### Warum überschreiben?
-- Debugging oder Überwachung hinzufügen.
-- Ereignisse in bestimmten Umgebungen einschränken (z.B. in der Testumgebung deaktivieren).
-- Mit einer anderen Ereignisbibliothek integrieren.
+- Fügen Sie Debugging oder Monitoring hinzu.
+- Beschränken Sie Ereignisse in bestimmten Umgebungen (z. B. deaktivieren in der Testumgebung).
+- Integrieren Sie eine andere Ereignisbibliothek.
## Wo Sie Ihre Ereignisse platzieren sollten
-Als Anfänger fragen Sie sich vielleicht: *Wo registriere ich all diese Ereignisse in meiner App?* Die Einfachheit von Flight bedeutet, dass es keine strenge Regel gibt—Sie können sie überall dort platzieren, wo es für Ihr Projekt sinnvoll ist. Allerdings hilft eine organisierte Struktur, Ihren Code zu pflegen, wenn Ihre App wächst. Hier sind einige praktische Optionen und Best Practices, die auf die leichte Natur von Flight zugeschnitten sind:
+Als Anfänger fragen Sie sich vielleicht: *Wo registriere ich all diese Ereignisse in meiner App?* Die einfachen Regeln von Flight bedeuten, dass es kein strenges Regelwerk gibt—Sie können sie dort platzieren, wo es für Ihr Projekt sinnvoll ist. Dennoch hilft es, sie organisiert zu halten, damit Sie Ihren Code verwalten können, wenn Ihre App wächst. Hier sind einige praktische Optionen und Best Practices, angepasst an die Leichtigkeit von Flight:
-### Option 1: In Ihrem Haupt-`index.php`
-Für kleine Apps oder schnelle Prototypen können Sie Ereignisse direkt in Ihrer `index.php`-Datei neben Ihren Routen registrieren. Dies hält alles an einem Ort, was in Ordnung ist, wenn Einfachheit Ihre Priorität ist.
+### Option 1: In Ihrer Haupt-`index.php`
+Für kleine Apps oder schnelle Prototypen können Sie Ereignisse direkt in Ihrer `index.php`-Datei zusammen mit Ihren Routen registrieren. Das hält alles an einem Ort, was in Ordnung ist, wenn Einfachheit Ihre Priorität ist.
```php
require 'vendor/autoload.php';
@@ -128,18 +128,18 @@ Flight::onEvent('user.login', function ($username) {
// Routen definieren
Flight::route('/login', function () {
- $username = 'bob';
+ $username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Angemeldet!";
+ echo "Eingeloggt!";
});
Flight::start();
```
-- **Vorteile**: Einfach, keine zusätzlichen Dateien, ideal für kleine Projekte.
-- **Nachteile**: Kann unübersichtlich werden, wenn Ihre App mit mehr Ereignissen und Routen wächst.
+- **Vorteile**: Einfach, keine zusätzlichen Dateien, großartig für kleine Projekte.
+- **Nachteile**: Kann chaotisch werden, wenn Ihre App mit mehr Ereignissen und Routen wächst.
### Option 2: Eine separate `events.php`-Datei
-Für eine etwas größere App sollten Sie in Betracht ziehen, die Ereignisregistrierungen in eine separate Datei wie `app/config/events.php` zu verschieben. Binden Sie diese Datei in Ihre `index.php` vor Ihren Routen ein. Dies ahmt nach, wie Routen oft in Flight-Projekten in `app/config/routes.php` organisiert sind.
+Für eine etwas größere App sollten Sie in Betracht ziehen, die Ereignisregistrierungen in einer speziellen Datei wie `app/config/events.php` zu verschieben. Binden Sie diese Datei in Ihre `index.php` ein, bevor Sie Ihre Routen definieren. Dies ahmt die Organisation von Routen in `app/config/routes.php` in Flight-Projekten nach.
```php
// app/config/events.php
@@ -158,24 +158,24 @@ require 'vendor/autoload.php';
require 'app/config/events.php';
Flight::route('/login', function () {
- $username = 'bob';
+ $username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Angemeldet!";
+ echo "Eingeloggt!";
});
Flight::start();
```
-- **Vorteile**: Hält `index.php` auf das Routing konzentriert, organisiert Ereignisse logisch, leicht zu finden und zu bearbeiten.
-- **Nachteile**: Fügt ein klein wenig Struktur hinzu, was sich für sehr kleine Apps übertrieben anfühlen kann.
+- **Vorteile**: Hält `index.php` auf Routing konzentriert, organisiert Ereignisse logisch, leicht zu finden und zu bearbeiten.
+- **Nachteile**: Fügt ein kleines bisschen Struktur hinzu, was sich für sehr kleine Apps übertrieben anfühlen könnte.
-### Option 3: Nahe dem Ort, wo sie ausgelöst werden
-Ein weiterer Ansatz besteht darin, Ereignisse in der Nähe von dort zu registrieren, wo sie ausgelöst werden, z. B. innerhalb eines Controllers oder einer Routen-Definition. Dies funktioniert gut, wenn ein Ereignis spezifisch für einen Teil Ihrer App ist.
+### Option 3: In der Nähe, wo sie ausgelöst werden
+Ein anderer Ansatz besteht darin, Ereignisse dort zu registrieren, wo sie ausgelöst werden, z. B. in einem Controller oder einer Routenbeschreibung. Dies funktioniert gut, wenn ein Ereignis spezifisch für einen Teil Ihrer App ist.
```php
Flight::route('/signup', function () {
// Ereignis hier registrieren
Flight::onEvent('user.registered', function ($email) {
- echo "Willkommens-E-Mail gesendet an $email!";
+ echo "Willkommens-E-Mail an $email gesendet!";
});
$email = 'jane@example.com';
@@ -183,16 +183,16 @@ Flight::route('/signup', function () {
echo "Angemeldet!";
});
```
-- **Vorteile**: Hält verwandte Codes zusammen, gut für isolierte Funktionen.
-- **Nachteile**: Verstreut Ereignisregistrierungen, was es schwieriger macht, alle Ereignisse auf einmal zu sehen; das Risiko doppelter Registrierungen, wenn man nicht vorsichtig ist.
+- **Vorteile**: Hält verwandten Code zusammen, gut für isolierte Funktionen.
+- **Nachteile**: Streut Ereignisregistrierungen, wodurch es schwieriger wird, alle Ereignisse auf einmal zu sehen; Risiken von doppelten Registrierungen, wenn man nicht vorsichtig ist.
### Best Practice für Flight
-- **Einfach beginnen**: Für winzige Apps setzen Sie Ereignisse in `index.php`. Es ist schnell und passt zur Minimalismus von Flight.
-- **Intelligent wachsen**: Wenn Ihre App wächst (z. B. mehr als 5-10 Ereignisse), verwenden Sie eine Datei `app/config/events.php`. Es ist ein natürlicher Schritt, ähnlich wie die Organisation von Routen, und hält Ihren Code ordentlich, ohne komplexe Frameworks hinzuzufügen.
-- **Vermeiden Sie Überengineering**: Erstellen Sie keine vollwertige „Ereignis-Manager“-Klasse oder -Verzeichnis, es sei denn, Ihre App wird riesig—Flight gedeiht in Einfachheit, also halten Sie es leichtgewichtig.
+- **Beginnen Sie einfach**: Für winzige Apps, legen Sie Ereignisse in `index.php`. Es ist schnell und entspricht der Minimalismus von Flight.
+- **Intelligent wachsen**: Wenn Ihre App wächst (z. B. mehr als 5-10 Ereignisse), verwenden Sie eine `app/config/events.php`-Datei. Es ist ein natürlicher nächster Schritt, ähnlich der Organisation von Routen, und hält Ihren Code aufgeräumt, ohne komplexe Frameworks hinzuzufügen.
+- **Überengineering vermeiden**: Erstellen Sie keine vollwertige „Ereignismanager“-Klasse oder -Verzeichnis, es sei denn, Ihre App wird riesig—Flight gedeiht in Einfachheit, also halten Sie es leichtgewichtig.
-### Tipp: Gruppieren nach Zweck
-In `events.php` gruppieren Sie verwandte Ereignisse (z.B. alle benutzerbezogenen Ereignisse zusammen) mit Kommentaren zur Klarheit:
+### Tipp: Gruppierung nach Zweck
+In der `events.php` sollten verwandte Ereignisse (z. B. alle benutzerbezogenen Ereignisse zusammen) mit Kommentaren zur Klarheit gruppiert werden:
```php
// app/config/events.php
@@ -210,7 +210,7 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-Diese Struktur skalierbar und bleibt für Anfänger freundlich.
+Diese Struktur skaliert gut und bleibt anfängerfreundlich.
## Beispiele für Anfänger
@@ -226,22 +226,22 @@ Flight::onEvent('user.login', function ($username) {
// Schritt 2: Auslösen in Ihrer App
Flight::route('/login', function () {
- $username = 'bob'; // Angenommen, dies kommt von einem Formular
+ $username = 'bob'; // Angenommen, dies stammt aus einem Formular
Flight::triggerEvent('user.login', $username);
echo "Hallo, $username!";
});
```
-**Warum es nützlich ist**: Der Anmeldecode muss nichts über das Protokollieren wissen—er löst einfach das Ereignis aus. Später können Sie mehr Zuhörer hinzufügen (z.B. eine Willkommens-E-Mail senden), ohne die Route zu ändern.
+**Warum es nützlich ist**: Der Anmeldecode muss nicht über die Protokollierung Bescheid wissen—er löst einfach das Ereignis aus. Sie können später weitere Listener hinzufügen (z. B. eine Willkommens-E-Mail senden), ohne die Route zu ändern.
-### Beispiel 2: Benachrichtigen über neue Benutzer
+### Beispiel 2: Benachrichtigung über neue Benutzer
```php
-// Listener für neue Registrierungen
+// Listener für neue Registrierung
Flight::onEvent('user.registered', function ($email, $name) {
- // Simulation des Sendens einer E-Mail
- echo "E-Mail gesendet an $email: Willkommen, $name!";
+ // Simuliert das Senden einer E-Mail
+ echo "E-Mail an $email gesendet: Willkommen, $name!";
});
-// Auslösen, wenn jemand sich anmeldet
+// Auslösen, wenn sich jemand anmeldet
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
@@ -249,13 +249,13 @@ Flight::route('/signup', function () {
echo "Danke für Ihre Anmeldung!";
});
```
-**Warum es nützlich ist**: Die Anmeldelogik konzentriert sich auf das Erstellen des Benutzers, während das Ereignis sich um die Benachrichtigungen kümmert. Später könnten Sie mehr Listener hinzufügen (z.B. das Protokollieren der Anmeldung).
+**Warum es nützlich ist**: Die Registrierungslogik konzentriert sich auf die Erstellung des Benutzers, während das Ereignis die Benachrichtigungen verarbeitet. Sie könnten später mehr Listener hinzufügen (z. B. die Anmeldung protokollieren).
### Beispiel 3: Leeren eines Caches
```php
-// Listener zum Leeren eines Caches
+// Listener zum Löschen eines Caches
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Leeren des Sitzungs-caches, falls zutreffend
+ unset($_SESSION['pages'][$pageId]); // Clears session cache if applicable
echo "Cache für Seite $pageId gelöscht.";
});
@@ -270,20 +270,26 @@ Flight::route('/edit-page/(@id)', function ($pageId) {
## Best Practices
-- **Ereignisse klar benennen**: Verwenden Sie spezifische Namen wie `'user.login'` oder `'page.updated'`, sodass klar nachvollzogen werden kann, was sie tun.
-- **Listener einfach halten**: Langsame oder komplexe Aufgaben sollten nicht in Listenern stehen—halten Sie Ihre App schnell.
-- **Testen Sie Ihre Ereignisse**: Lösen Sie sie manuell aus, um sicherzustellen, dass Listener wie erwartet funktionieren.
-- **Verwenden Sie Ereignisse weise**: Sie sind großartig für die Entkopplung, aber zu viele können Ihren Code schwer nachvollziehbar machen—verwenden Sie sie, wenn es sinnvoll ist.
+- **Ereignisse klar benennen**: Verwenden Sie spezifische Namen wie `'user.login'` oder `'page.updated'`, damit offensichtlich ist, was sie tun.
+- **Halten Sie Listener einfach**: Legen Sie keine langsamen oder komplexen Aufgaben in Listenern—halten Sie Ihre App schnell.
+- **Testen Sie Ihre Ereignisse**: Lösen Sie sie manuell aus, um sicherzustellen, dass die Listener wie erwartet funktionieren.
+- **Verwenden Sie Ereignisse weise**: Sie sind großartig für die Entkopplung, aber zu viele können Ihren Code schwer zu folgen machen—verwenden Sie sie, wenn es sinnvoll ist.
-Das Ereignissystem in Flight PHP, mit `Flight::onEvent()` und `Flight::triggerEvent()`, bietet Ihnen eine einfache und dennoch leistungsstarke Möglichkeit, flexible Anwendungen zu erstellen. Indem Sie verschiedenen Teilen Ihrer App erlauben, über Ereignisse miteinander zu kommunizieren, können Sie Ihren Code organisiert, wiederverwendbar und leicht erweiterbar halten. Ob Sie Aktionen protokollieren, Benachrichtigungen senden oder Updates verwalten, Ereignisse helfen Ihnen, dies zu tun, ohne Ihre Logik zu verkomplizieren. Darüber hinaus haben Sie mit der Möglichkeit, diese Methoden zu überschreiben, die Freiheit, das System an Ihre Bedürfnisse anzupassen. Beginnen Sie klein mit einem einzelnen Ereignis und beobachten Sie, wie es die Struktur Ihrer App transformiert!
+Das Ereignissystem in Flight PHP, mit `Flight::onEvent()` und `Flight::triggerEvent()`, bietet Ihnen eine einfache, aber leistungsstarke Möglichkeit, flexible Anwendungen zu erstellen. Indem Sie verschiedenen Teilen Ihrer App ermöglichen, über Ereignisse miteinander zu kommunizieren, können Sie Ihren Code organisiert, wiederverwendbar und leicht erweiterbar halten. Egal, ob Sie Aktionen protokollieren, Benachrichtigungen senden oder Updates verwalten, Ereignisse helfen Ihnen dabei, ohne die Logik zu verknüpfen. Darüber hinaus haben Sie die Freiheit, diese Methoden zu überschreiben, um das System an Ihre Bedürfnisse anzupassen. Beginnen Sie klein mit einem einzigen Ereignis, und beobachten Sie, wie es die Struktur Ihrer App transformiert!
## Eingebaute Ereignisse
-Flight PHP verfügt über einige eingebaute Ereignisse, die Sie verwenden können, um in den Lebenszyklus des Frameworks einzugreifen. Diese Ereignisse werden an bestimmten Punkten im Anfrage-/Antwortzyklus ausgelöst, sodass Sie benutzerdefinierte Logik ausführen können, wenn bestimmte Aktionen auftreten.
+Flight PHP kommt mit einigen integrierten Ereignissen, die Sie verwenden können, um in den Lebenszyklus des Frameworks einzuhaken. Diese Ereignisse werden an bestimmten Punkten im Anfrage-/Antwortzyklus ausgelöst, sodass Sie benutzerdefinierte Logik ausführen können, wenn bestimmte Aktionen auftreten.
### Liste der eingebauten Ereignisse
-- `flight.request.received`: Wird ausgelöst, wenn eine Anfrage empfangen, analysiert und verarbeitet wird.
-- `flight.route.middleware.before`: Wird ausgelöst, nachdem das "before"-Middleware ausgeführt wurde.
-- `flight.route.middleware.after`: Wird ausgelöst, nachdem das "after"-Middleware ausgeführt wurde.
-- `flight.route.executed`: Wird ausgelöst, nachdem eine Route ausgeführt und verarbeitet wurde.
-- `flight.response.sent`: Wird ausgelöst, nachdem eine Antwort an den Client gesendet wurde.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` Wird ausgelöst, wenn eine Anfrage empfangen, geparst und verarbeitet wird.
+- **flight.error**: `function(Throwable $exception)` Wird ausgelöst, wenn ein Fehler während des Lebenszyklus der Anfrage auftritt.
+- **flight.redirect**: `function(string $url, int $status_code)` Wird ausgelöst, wenn eine Weiterleitung initiiert wird.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Wird ausgelöst, wenn der Cache für einen bestimmten Schlüssel überprüft wird und ob der Cache einen Treffer oder ein Fehlschlagen hat.
+- **flight.middleware.before**: `function(Route $route)` Wird ausgelöst, nachdem die Middleware vor der Ausführung ausgeführt wurde.
+- **flight.middleware.after**: `function(Route $route)` Wird ausgelöst, nachdem die Middleware nach der Ausführung ausgeführt wurde.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Wird ausgelöst, nachdem eine Middleware ausgeführt wurde.
+- **flight.route.matched**: `function(Route $route)` Wird ausgelöst, wenn eine Route übereinstimmt, aber noch nicht ausgeführt wird.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Wird ausgelöst, nachdem eine Route ausgeführt und verarbeitet wurde. `$executionTime` ist die Zeit, die benötigt wurde, um die Route auszuführen (Controller aufzurufen usw.).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Wird ausgelöst, nachdem eine Ansicht gerendert wurde. `$executionTime` ist die Zeit, die zum Rendern der Vorlage benötigt wurde. **Hinweis: Wenn Sie die Methode `render` überschreiben, müssen Sie dieses Ereignis erneut auslösen.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Wird ausgelöst, nachdem eine Antwort an den Client gesendet wurde. `$executionTime` ist die Zeit, die benötigt wurde, um die Antwort zu erstellen.
\ No newline at end of file
diff --git a/content/v3/en/awesome-plugins/apm.md b/content/v3/en/awesome-plugins/apm.md
new file mode 100644
index 0000000..868f134
--- /dev/null
+++ b/content/v3/en/awesome-plugins/apm.md
@@ -0,0 +1,291 @@
+# FlightPHP APM Documentation
+
+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!
+
+## Why APM Matters
+
+Picture this: your app is a busy restaurant. Without a way to track how long orders take or where the kitchen’s bogging down, you’re guessing why customers are leaving grumpy. APM is your sous-chef—it watches every step, from incoming requests to database queries, and flags anything slowing you down. Slow pages lose users (studies say 53% bounce if a site takes over 3 seconds to load!), and APM helps you catch those issues *before* they sting. It’s proactive peace of mind—fewer “why is this broken?” moments, more “look how slick this runs!” wins.
+
+## Installation
+
+Get started with Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+You’ll need:
+- **PHP 7.4+**: Keeps us compatible with LTS Linux distros while supporting modern PHP.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: The lightweight framework we’re boosting.
+
+## Getting Started
+
+Here’s your step-by-step to APM awesomeness:
+
+### 1. Register the APM
+
+Drop this into your `index.php` or a `services.php` file to start tracking:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**What’s happening here?**
+- `LoggerFactory::create()` grabs your config (more on that soon) and sets up a logger—SQLite by default.
+- `Apm` is the star—it listens to Flight’s events (requests, routes, errors, etc.) and collects metrics.
+- `bindEventsToFlightInstance($app)` ties it all to your Flight app.
+
+**Pro Tip: Sampling**
+If your app’s busy, logging *every* request might overload things. Use a sample rate (0.0 to 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Logs 10% of requests
+```
+
+This keeps performance snappy while still giving you solid data.
+
+### 2. Configure It
+
+Run this to whip up your `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**What’s this do?**
+- Launches a wizard asking where raw metrics come from (source) and where processed data goes (destination).
+- Default is SQLite—e.g., `sqlite:/tmp/apm_metrics.sqlite` for source, another for destination.
+- You’ll end up with a config like:
+ ```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"
+ }
+ }
+ ```
+
+> This process will also ask if you want to run the migrations for this setup. If you're setting this up for your first time, the answer is yes.
+
+**Why two locations?**
+Raw metrics pile up fast (think unfiltered logs). The worker processes them into a structured destination for the dashboard. Keeps things tidy!
+
+### 3. Process Metrics with the Worker
+
+The worker turns raw metrics into dashboard-ready data. Run it once:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**What’s it doing?**
+- Reads from your source (e.g., `apm_metrics.sqlite`).
+- Processes up to 100 metrics (default batch size) into your destination.
+- Stops when done or if no metrics are left.
+
+**Keep It Running**
+For live apps, you’ll want continuous processing. Here are your options:
+
+- **Daemon Mode**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Runs forever, processing metrics as they come. Great for dev or small setups.
+
+- **Crontab**:
+ Add this to your crontab (`crontab -e`):
+ ```bash
+ * * * * * php /path/to/project/vendor/bin/runway apm:worker
+ ```
+ Fires every minute—perfect for production.
+
+- **Tmux/Screen**:
+ Start a detachable session:
+ ```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
+ ```
+ Keeps it running even if you log out.
+
+- **Custom Tweaks**:
+ ```bash
+ php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
+ ```
+ - `--batch_size 50`: Process 50 metrics at a time.
+ - `--max_messages 1000`: Stop after 1000 metrics.
+ - `--timeout 300`: Quit after 5 minutes.
+
+**Why bother?**
+Without the worker, your dashboard’s empty. It’s the bridge between raw logs and actionable insights.
+
+### 4. Launch the Dashboard
+
+See your app’s vitals:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**What’s this?**
+- Spins up a PHP server at `http://localhost:8001/apm/dashboard`.
+- Shows request logs, slow routes, error rates, and more.
+
+**Customize It**:
+```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 from any IP (handy for remote viewing).
+- `--port 8080`: Use a different port if 8001’s taken.
+- `--php-path`: Point to PHP if it’s not in your PATH.
+
+Hit the URL in your browser and explore!
+
+#### Production Mode
+
+For production, you may have to try a few techniques to get the dashboard running since there are probably firewalls and other security measures in place. Here are a few options:
+
+- **Use a Reverse Proxy**: Set up Nginx or Apache to forward requests to the dashboard.
+- **SSH Tunnel**: If you can SSH into the server, use `ssh -L 8080:localhost:8001
+youruser@yourserver` to tunnel the dashboard to your local machine.
+- **VPN**: If your server is behind a VPN, connect to it and access the dashboard directly.
+- **Configure Firewall**: Open port 8001 for your IP or the server’s network. (or whatever port you set it to).
+- **Configure Apache/Nginx**: If you have a web server in front of your application, you can configure it to a domain or subdomain. If you do this, you'll set the document root to `/path/to/your/project/vendor/flightphp/apm/dashboard`
+
+#### Want a different dashboard?
+
+You can build your own dashboard if you want! Look at the vendor/flightphp/apm/src/apm/presenter directory for ideas on how to present the data for your own dashboard!
+
+## Dashboard Features
+
+The dashboard is your APM HQ—here’s what you’ll see:
+
+- **Request Log**: Every request with timestamp, URL, response code, and total time. Click “Details” for middleware, queries, and errors.
+- **Slowest Requests**: Top 5 requests hogging time (e.g., “/api/heavy” at 2.5s).
+- **Slowest Routes**: Top 5 routes by average time—great for spotting patterns.
+- **Error Rate**: Percentage of requests failing (e.g., 2.3% 500s).
+- **Latency Percentiles**: 95th (p95) and 99th (p99) response times—know your worst-case scenarios.
+- **Response Code Chart**: Visualize 200s, 404s, 500s over time.
+- **Long Queries/Middleware**: Top 5 slow database calls and middleware layers.
+- **Cache Hit/Miss**: How often your cache saves the day.
+
+**Extras**:
+- Filter by “Last Hour,” “Last Day,” or “Last Week.”
+- Toggle dark mode for those late-night sessions.
+
+**Example**:
+A request to `/users` might show:
+- Total Time: 150ms
+- Middleware: `AuthMiddleware->handle` (50ms)
+- Query: `SELECT * FROM users` (80ms)
+- Cache: Hit on `user_list` (5ms)
+
+## Adding Custom Events
+
+Track anything—like an API call or payment process:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Where’s it show up?**
+In the dashboard’s request details under “Custom Events”—expandable with pretty JSON formatting.
+
+**Use Case**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Now you’ll see if that API’s dragging your app down!
+
+## Database Monitoring
+
+Track PDO queries like this:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**What You Get**:
+- Query text (e.g., `SELECT * FROM users WHERE id = ?`)
+- Execution time (e.g., 0.015s)
+- Row count (e.g., 42)
+
+**Heads Up**:
+- **Optional**: Skip this if you don’t need DB tracking.
+- **PdoWrapper Only**: Core PDO isn’t hooked yet—stay tuned!
+- **Performance Warning**: Logging every query on a DB-heavy site can slow things down. Use sampling (`$Apm = new Apm($ApmLogger, 0.1)`) to lighten the load.
+
+**Example Output**:
+- Query: `SELECT name FROM products WHERE price > 100`
+- Time: 0.023s
+- Rows: 15
+
+## Worker Options
+
+Tune the worker to your liking:
+
+- `--timeout 300`: Stops after 5 minutes—good for testing.
+- `--max_messages 500`: Caps at 500 metrics—keeps it finite.
+- `--batch_size 200`: Processes 200 at once—balances speed and memory.
+- `--daemon`: Runs non-stop—ideal for live monitoring.
+
+**Example**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+Runs for an hour, processing 100 metrics at a time.
+
+## Upgrading
+
+If you are upgrading to a newer version of the APM, there is a chance that there are database migrations that need to be run. You can do this by running the following command:
+
+```bash
+php vendor/bin/runway apm:migrate
+```
+This will run any migrations that are needed to update the database schema to the latest version.
+
+**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.
+
+## Troubleshooting
+
+Stuck? Try these:
+
+- **No Dashboard Data?**
+ - Is the worker running? Check `ps aux | grep apm:worker`.
+ - Config paths match? Verify `.runway-config.json` DSNs point to real files.
+ - Run `php vendor/bin/runway apm:worker` manually to process pending metrics.
+
+- **Worker Errors?**
+ - Peek at your SQLite files (e.g., `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`).
+ - Check PHP logs for stack traces.
+
+- **Dashboard Won’t Start?**
+ - Port 8001 in use? Use `--port 8080`.
+ - PHP not found? Use `--php-path /usr/bin/php`.
+ - Firewall blocking? Open the port or use `--host localhost`.
+
+- **Too Slow?**
+ - Lower the sample rate: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Reduce batch size: `--batch_size 20`.
\ 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 54f3814..3d59d92 100644
--- a/content/v3/en/awesome-plugins/awesome_plugins.md
+++ b/content/v3/en/awesome-plugins/awesome_plugins.md
@@ -9,6 +9,11 @@ API documentation is crucial for any API. It helps developers understand how to
- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blog post written by Daniel Schreiber on how to use the OpenAPI Spec with FlightPHP to build out your API using an API first approach.
- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI is a great tool to help you generate API documentation for your Flight projects. It's very easy to use and can be customized to fit your needs. This is the PHP library to help you generate the Swagger documentation.
+## Application Performance Monitoring (APM)
+
+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.
+- beta[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.
+
## Authentication/Authorization
Authentication and Authorization are crucial for any application that requires controls to be in place for who can access what.
diff --git a/content/v3/en/awesome-plugins/session.md b/content/v3/en/awesome-plugins/session.md
index 7ba575d..896f5a8 100644
--- a/content/v3/en/awesome-plugins/session.md
+++ b/content/v3/en/awesome-plugins/session.md
@@ -62,13 +62,14 @@ Flight::start();
You can customize the session handler by passing an array of options when registering:
```php
-$app->register('session', Session::class, [
+// Yep, it's a double array :)
+$app->register('session', Session::class, [ [
'save_path' => '/custom/path/to/sessions', // Directory for session files
'encryption_key' => 'a-secure-32-byte-key-here', // Enable encryption (32 bytes recommended for AES-256-CBC)
'auto_commit' => false, // Disable auto-commit for manual control
'start_session' => true, // Start session automatically (default: true)
'test_mode' => false // Enable test mode for development
-]);
+] ]);
```
### Configuration Options
diff --git a/content/v3/en/learn/events.md b/content/v3/en/learn/events.md
index b690c27..7c0adb4 100644
--- a/content/v3/en/learn/events.md
+++ b/content/v3/en/learn/events.md
@@ -285,9 +285,10 @@ Flight PHP comes with a few built-in events that you can use to hook into the fr
- **flight.request.received**: `function(Request $request)` Triggered when a request is received, parsed and processed.
- **flight.error**: `function(Throwable $exception)` Triggered when an error occurs during the request lifecycle.
- **flight.redirect**: `function(string $url, int $status_code)` Triggered when a redirect is initiated.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Triggered when the cache is checked for a specific key and if the cache hit or miss.
- **flight.middleware.before**: `function(Route $route)`Triggered after the before middleware is executed.
- **flight.middleware.after**: `function(Route $route)` Triggered after the after middleware is executed.
-- **flight.middleware.executed**: `function(Route $route, $middleware)` Triggered after any middleware is executed
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Triggered after any middleware is executed
- **flight.route.matched**: `function(Route $route)` Triggered when a route is matched, but not yet run.
- **flight.route.executed**: `function(Route $route, float $executionTime)` Triggered after a route is executed and processed. `$executionTime` is time it took to execute the route (call the controller, etc).
- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Triggered after a view is rendered. `$executionTime` is time it took to render the template. **Note: If you override the `render` method, you will need to re-trigger this event.**
diff --git a/content/v3/es/awesome-plugins/apm.md b/content/v3/es/awesome-plugins/apm.md
new file mode 100644
index 0000000..78e2d98
--- /dev/null
+++ b/content/v3/es/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# Documentación de FlightPHP APM
+
+¡Bienvenido a FlightPHP APM—el entrenador personal de rendimiento de tu aplicación! Esta guía es tu hoja de ruta para configurar, usar y dominar el Monitoreo de Rendimiento de Aplicaciones (APM) con FlightPHP. Ya sea que estés buscando solicitudes lentas o simplemente quieras disfrutar de los gráficos de latencia, estamos aquí para ayudarte. ¡Hagamos que tu aplicación sea más rápida, que tus usuarios sean más felices y que tus sesiones de depuración sean un paseo!
+
+## Por qué APM es importante
+
+Imagina esto: tu aplicación es un restaurante ocupado. Sin una forma de rastrear cuánto tiempo tardan los pedidos o dónde se está atascando la cocina, estás adivinando por qué los clientes se van enojados. APM es tu sous-chef: observa cada paso, desde las solicitudes entrantes hasta las consultas a la base de datos, y señala cualquier cosa que te esté ralentizando. Las páginas lentas pierden usuarios (¡los estudios dicen que el 53% se van si un sitio tarda más de 3 segundos en cargar!), y APM te ayuda a detectar esos problemas *antes* de que duelan. Es tranquilidad proactiva: menos momentos de “¿por qué se rompió esto?”, más victorias de “¡mira lo bien que funciona!”.
+
+## Instalación
+
+Empieza con Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Necesitarás:
+- **PHP 7.4+**: Nos mantiene compatibles con distribuciones de Linux LTS mientras soportamos PHP moderno.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: El marco ligero que estamos potenciando.
+
+## Comenzando
+
+Aquí tienes tu paso a paso hacia la genialidad de APM:
+
+### 1. Registra el APM
+
+Agrégalo a tu `index.php` o a un archivo `services.php` para comenzar a rastrear:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**¿Qué está sucediendo 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 vincula todo a tu aplicación Flight.
+
+**Consejo Profesional: Muestreo**
+Si tu aplicación 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 aún te proporciona datos sólidos.
+
+### 2. Configúralo
+
+Ejecuta esto para crear tu `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**¿Qué hace esto?**
+- Inicia un asistente que pregunta de dónde provienen las métricas brutas (fuente) y a dónde va la información procesada (destino).
+- El valor 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:
+ ```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"
+ }
+ }
+ ```
+
+**¿Por qué dos ubicaciones?**
+Las métricas brutas se acumulan rápido (piensa en registros sin filtrar). El trabajador las procesa en un destino estructurado para el panel. ¡Mantiene las cosas ordenadas!
+
+### 3. Procesa métricas con el trabajador
+
+El trabajador convierte métricas brutas en datos listos para el panel. Ejecútalo una vez:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**¿Qué está haciendo?**
+- 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 se completa o si no quedan métricas.
+
+**Mantenlo en ejecución**
+Para aplicaciones en vivo, querrás procesamiento continuo. Aquí están tus opciones:
+
+- **Modo Daemon**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Se ejecuta para siempre, procesando métricas a medida que llegan. Ideal para desarrollo 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.
+
+- **Tmux/Screen**:
+ Inicia una sesión desacoplable:
+ ```bash
+ tmux new -s apm-worker
+ php vendor/bin/runway apm:worker --daemon
+ # Ctrl+B, luego D para desacoplar; `tmux attach -t apm-worker` para reconectar
+ ```
+ Se mantiene en ejecución 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`: Procesa 50 métricas a la vez.
+ - `--max_messages 1000`: Detiene después de 1000 métricas.
+ - `--timeout 300`: Sal de la ejecución después de 5 minutos.
+
+**¿Por qué molestarse?**
+Sin el trabajador, tu panel estará vacío. Es el puente entre los registros brutos y las percepciones accionables.
+
+### 4. Lanza el panel
+
+Ve los vitales de tu aplicación:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**¿Qué es esto?**
+- Levanta un servidor PHP en `http://localhost:8001/apm/dashboard`.
+- Muestra registros de solicitudes, rutas lentas, tasas de error, y más.
+
+**Personalízalo**:
+```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`: Accesible desde cualquier IP (útil para visualización remota).
+- `--port 8080`: Usa un puerto diferente si 8001 está ocupado.
+- `--php-path`: Indica dónde está PHP si no está en tu PATH.
+
+¡Accede a la URL en tu navegador y explora!
+
+#### Modo Producción
+
+Para producción, es posible que debas probar algunas técnicas para que el panel funcione, ya que probablemente hay cortafuegos y otras medidas de seguridad en su lugar. Aquí hay algunas opciones:
+
+- **Usa un Proxy Inverso**: Configura Nginx o Apache para redirigir solicitudes al panel.
+- **Túnel SSH**: Si puedes SSH en el servidor, usa `ssh -L 8080:localhost:8001 tuusuario@tu servidor` 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 Cortafuegos**: Abre el puerto 8001 para tu IP o la red del servidor. (o cualquier puerto que hayas configurado).
+- **Configura Apache/Nginx**: Si tienes un servidor web delante de tu aplicación, puedes configurarlo a un dominio o subdominio. Si haces esto, establecerás la raíz del documento en `/path/to/your/project/vendor/flightphp/apm/dashboard`
+
+#### ¿Quieres un panel diferente?
+
+¡Puedes construir tu propio panel si lo deseas! Mira en el directorio vendor/flightphp/apm/src/apm/presenter para ideas sobre cómo presentar los datos para tu propio panel.
+
+## Características del Panel
+
+El panel es tu HQ de APM—esto es 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 solicitudes que más tiempo consumen (por ejemplo, “/api/heavy” en 2.5s).
+- **Rutas Más Lentas**: Las 5 rutas por tiempo promedio—genial para detectar patrones.
+- **Tasa de Error**: Porcentaje de solicitudes fallidas (por ejemplo, 2.3% 500s).
+- **Percentiles de Latencia**: Tiempos de respuesta del 95% (p95) y 99% (p99)—conoce tus peores escenarios.
+- **Gráfico de Códigos de Respuesta**: Visualiza los 200s, 404s, 500s con el tiempo.
+- **Consultas/Llamadas Lentass**: Las 5 llamadas a la base de datos y capas de middleware más lentas.
+- **Aciertos/Fallos de Caché**: La frecuencia con la que tu caché salva el día.
+
+**Extras**:
+- Filtrar por “Última Hora,” “Último Día,” o “Última Semana.”
+- Cambiar a modo oscuro para esas sesiones nocturnas.
+
+**Ejemplo**:
+Una solicitud a `/users` podría mostrar:
+- Tiempo Total: 150ms
+- Middleware: `AuthMiddleware->handle` (50ms)
+- Consulta: `SELECT * FROM users` (80ms)
+- Caché: Acierto en `user_list` (5ms)
+
+## Agregando Eventos Personalizados
+
+Rastrea cualquier cosa—como una llamada a la API o un proceso de pago:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**¿Dónde aparece?**
+En los detalles de la solicitud del panel bajo “Eventos Personalizados”—expandible con un bonito formato JSON.
+
+**Caso de Uso**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+¡Ahora verás si esa API está arrastrando tu aplicación hacia abajo!
+
+## Monitoreo de Base de Datos
+
+Rastrea consultas PDO de esta manera:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**¿Qué obtienes?**
+- Texto de consulta (por ejemplo, `SELECT * FROM users WHERE id = ?`)
+- Tiempo de ejecución (por ejemplo, 0.015s)
+- Cuenta de filas (por ejemplo, 42)
+
+**Advertencia**:
+- **Opcional**: Omítelo si no necesitas rastrear la base de datos.
+- **Solo PdoWrapper**: El núcleo de PDO aún no está conectado—¡mantente atento!
+- **Advertencia de Rendimiento**: Registrar cada consulta en un sitio con muchas bases de datos puede ralentizar las cosas. Usa muestreo (`$Apm = new Apm($ApmLogger, 0.1)`) para aligerar la carga.
+
+**Ejemplo de Salida**:
+- Consulta: `SELECT name FROM products WHERE price > 100`
+- Tiempo: 0.023s
+- Filas: 15
+
+## Opciones del Trabajador
+
+Ajusta el trabajador a tu gusto:
+
+- `--timeout 300`: Detiene después de 5 minutos—bueno para pruebas.
+- `--max_messages 500`: Limita a 500 métricas—mantiene las cosas finitas.
+- `--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.
+
+## Resolución de Problemas
+
+¿Estancado? Prueba esto:
+
+- **¿No hay datos en el panel?**
+ - ¿Está en ejecución el trabajador? Verifica `ps aux | grep apm:worker`.
+ - ¿Los caminos de configuración coinciden? Verifica que los DSNs de `.runway-config.json` apunten a archivos reales.
+ - Ejecuta `php vendor/bin/runway apm:worker` manualmente para procesar métricas pendientes.
+
+- **¿Errores en el trabajador?**
+ - Mira tus archivos SQLite (por ejemplo, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`).
+ - Revisa los registros de PHP en busca de rastros de pila.
+
+- **¿El panel no se inicia?**
+ - ¿Puerto 8001 usado? Usa `--port 8080`.
+ - ¿PHP no encontrado? Usa `--php-path /usr/bin/php`.
+ - ¿Cortafuegos bloqueando? Abre el puerto o usa `--host localhost`.
+
+- **¿Demasiado lento?**
+ - Reduce la tasa de muestreo: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Reduce el tamaño del lote: `--batch_size 20`.
\ 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 3fa167d..0df307f 100644
--- a/content/v3/es/awesome-plugins/awesome_plugins.md
+++ b/content/v3/es/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
-# Plugins Asombrosos
+# Complementos Asombrosos
-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 compatibles con el equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar.
+Flight es increíblemente extensible. Hay una serie de complementos que se pueden usar para añadir 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 la API
-La documentación de la 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 la API para tus proyectos Flight.
+La documentación de la 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 la documentación de la 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 primero de API.
-- [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 de 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 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 de Swagger.
+
+## Monitoreo del Rendimiento de la Aplicación (APM)
+
+El Monitoreo del Rendimiento de la Aplicación (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.
+- beta[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.
## Autenticación/Autorización
-La autenticación y la autorización son cruciales para cualquier aplicación que requiera controles sobre quién puede acceder a qué.
+La Autenticación y la Autorización son cruciales para cualquier aplicación que requiera controles sobre quién puede acceder a qué.
-- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de permisos de Flight oficial. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y a nivel de aplicación a tu aplicación.
+- official [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permisos oficial de Flight. Esta biblioteca es una forma simple de añadir permisos a nivel de usuario y de aplicación a tu aplicación.
-## Caching
+## Caché
-El caching es una excelente manera de acelerar tu aplicación. Hay varias bibliotecas de caching que se pueden utilizar 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 de caching en archivo PHP ligera, simple y autónoma.
+- official [flightphp/cache](/awesome-plugins/php-file-cache) - Clase de caché en archivo PHP liviana, simple y autónoma.
## CLI
-Las aplicaciones CLI son una excelente 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 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.
+- official [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight.
## Cookies
-Las cookies son una excelente manera de almacenar pequeñas cantidades de datos en el lado del cliente. Pueden usarse para almacenar preferencias del usuario, configuraciones de la aplicación y más.
+Las cookies son una gran manera de almacenar pequeñas cantidades de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de la 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 algunos complementos 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 varios paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles.
-- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles adicionales para ayudar con la depuración específicamente para proyectos Flight.
+- [tracy/tracy](/awesome-plugins/tracy) - Este es un controlador de errores con todas las funciones que se puede utilizar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y añadir tus propios paneles.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Utilizado con el [Tracy](/awesome-plugins/tracy) controlador de errores, este complemento añade 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 algunas son ORM completamente desarrolladas.
+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 algunas son ORM totalmente desarrollados.
-- oficial [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Envoltura PDO oficial de Flight que es parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escritura de consultas y su ejecución. No es un ORM.
-- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial de Flight. Gran pequeña biblioteca para recuperar y almacenar datos fácilmente en tu base de datos.
-- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para realizar un seguimiento de todos los cambios en la base de datos para tu proyecto.
+- official [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Envoltorio PDO oficial de Flight que forma parte del núcleo. Este es un envoltorio simple para ayudar a simplificar el proceso de escritura de consultas y ejecutarlas. No es un ORM.
+- official [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) - Complemento para rastrear todos los cambios en la base de datos para tu proyecto.
## Cifrado
-El cifrado es crucial para cualquier aplicación que almacene datos sensibles. Cifrar y descifrar los datos no es terriblemente difícil, pero almacenar adecuadamente la clave de cifrado [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 cifrado en un directorio público o comprometerla en tu repositorio de código.
+El cifrado es crucial para cualquier aplicación que almacene datos sensibles. Cifrar y descifrar los datos no es terriblemente complicado, pero almacenar correctamente la clave de cifrado [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 cifrado en un directorio público o comprometerla en tu repositorio de código.
- [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta es una biblioteca que se puede usar para cifrar y descifrar datos. Comenzar a usarla es bastante simple para comenzar a cifrar y descifrar datos.
-## Cola de Trabajo
+## Cola de Trabajos
-Las colas de trabajo 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 forma 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.
+- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue es una biblioteca que se puede usar para procesar trabajos de forma asíncrona. Se puede utilizar con beanstalkd, MySQL/MariaDB, SQLite y PostgreSQL.
## Sesión
-Las sesiones realmente no son útiles para APIs, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado y la 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 y la 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. Utiliza el manejo de sesiones incorporado de PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - Administrador de sesiones PHP (sin bloqueo, flash, segmento, cifrado de sesión). Utiliza PHP open_ssl para cifrado/descifrado opcional de datos de sesión.
+- official [flightphp/session](/awesome-plugins/session) - Biblioteca de Sesiones oficial de Flight. Esta es una biblioteca de sesiones simple que se puede usar para almacenar y recuperar datos de sesión. Utiliza el manejo de sesiones incorporado de PHP.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesiones PHP (sin bloqueo, flash, segmento, cifrado de sesiones). Utiliza PHP open_ssl para cifrado/descifrado opcional de datos de sesión.
## Plantillas
-Las plantillas son fundamentales para cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden utilizar con Flight.
+Las plantillas son fundamentales para cualquier aplicación web con una interfaz de usuario. Hay una serie de motores de plantillas que se pueden usar con Flight.
-- deprecated [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que es parte del núcleo. No se recomienda su uso 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 una sintaxis de PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones.
+- deprecated [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](/awesome-plugins/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 extender y añadir tus propios filtros y funciones.
## Contribuyendo
-¿Tienes un plugin que te gustaría compartir? ¡Envía una solicitud de extracción para agregarlo a la lista!
\ No newline at end of file
+¿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/tracy_extensions.md b/content/v3/es/awesome-plugins/tracy_extensions.md
index afb399f..a19d091 100644
--- a/content/v3/es/awesome-plugins/tracy_extensions.md
+++ b/content/v3/es/awesome-plugins/tracy_extensions.md
@@ -1,32 +1,32 @@
-# Tracy Flight Panel Extensions
+Tracy Flight Panel Extensions
=====
-This is a set of extensions to make working with Flight a little richer.
+Este es un conjunto de extensiones para hacer que trabajar con Flight sea un poco más enriquecedor.
-- Flight - Analyze all Flight variables.
-- Database - Analyze all queries that have run on the page (if you correctly initiate the database connection)
-- Request - Analyze all `$_SERVER` variables and examine all global payloads (`$_GET`, `$_POST`, `$_FILES`)
-- Session - Analyze all `$_SESSION` variables if sessions are active.
+- Flight - Analiza todas las variables de Flight.
+- Database - Analiza todas las consultas que se han ejecutado en la página (si inicias correctamente la conexión a la base de datos)
+- Request - Analiza todas las variables `$_SERVER` y examina todas las cargas útiles globales (`$_GET`, `$_POST`, `$_FILES`)
+- Session - Analiza todas las variables `$_SESSION` si las sesiones están activas.
-This is the Panel
+Este es el Panel

-And each panel displays very helpful information about your application!
+¡Y cada panel muestra información muy útil sobre su aplicación!



-Click [here](https://github.com/flightphp/tracy-extensions) to view the code.
+Haz clic [aquí](https://github.com/flightphp/tracy-extensions) para ver el código.
-Installation
+Instalación
-------
-Run `composer require flightphp/tracy-extensions --dev` and you're on your way!
+Ejecuta `composer require flightphp/tracy-extensions --dev` y ¡estarás en camino!
-Configuration
+Configuración
-------
-There is very little configuration you need to do to get this started. You will need to initiate the Tracy debugger prior to using this [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Hay muy poca configuración que necesitas hacer para empezar. Necesitarás iniciar el depurador Tracy antes de usar esto [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // This needs to be false or Tracy can't actually render :(
+ // Esto necesita ser falso o Tracy no puede renderizar realmente :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
-// routes and other things...
+// rutas y otras cosas...
Flight::start();
```
### Latte
-If you have Latte installed in your project, you can use the Latte panel to analyze your templates. You can pass in the Latte instance to the `TracyExtensionLoader` constructor with the `latte` key in the second parameter.
+Si tienes Latte instalado en tu proyecto, puedes usar el panel de Latte para analizar tus plantillas. Puedes pasar la instancia de Latte al constructor de `TracyExtensionLoader` con la clave `latte` en el segundo parámetro.
```php
@@ -101,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // this is where you add the Latte Panel to Tracy
+ // aquí es donde agregas el Panel de Latte a Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // This needs to be false or Tracy can't actually render :(
+ // Esto necesita ser falso o Tracy no puede renderizar realmente :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/es/learn/events.md b/content/v3/es/learn/events.md
index f9a7b02..4174fe8 100644
--- a/content/v3/es/learn/events.md
+++ b/content/v3/es/learn/events.md
@@ -1,43 +1,43 @@
# Sistema de Eventos en Flight PHP (v3.15.0+)
-Flight PHP introduce un sistema de eventos ligero e intuitivo que te permite registrar y activar eventos personalizados en tu aplicación. Con la adición de `Flight::onEvent()` y `Flight::triggerEvent()`, ahora puedes engancharte a momentos clave del ciclo de vida de tu aplicación o definir tus propios eventos para hacer tu código más modular y extensible. Estos métodos son parte de los **métodos mapeables** de Flight, lo que significa que puedes sobrescribir su comportamiento para adaptarlo a tus necesidades.
+Flight PHP introduce un sistema de eventos ligero e intuitivo que te permite registrar y activar eventos personalizados en tu aplicación. Con la adición de `Flight::onEvent()` y `Flight::triggerEvent()`, ahora puedes engancharte a momentos clave del ciclo de vida de tu aplicación o definir tus propios eventos para hacer tu código más modular y extensible. Estos métodos son parte de los **métodos mapeables** de Flight, lo que significa que puedes anular su comportamiento para adaptarlo a tus necesidades.
-Esta guía cubre todo lo que necesitas saber para comenzar con eventos, incluyendo por qué son valiosos, cómo usarlos y ejemplos prácticos para ayudar a los principiantes a entender su poder.
+Esta guía cubre todo lo que necesitas saber para empezar con los eventos, incluyendo por qué son valiosos, cómo utilizarlos y ejemplos prácticos para ayudar a los principiantes a entender su poder.
-## ¿Por qué usar eventos?
+## ¿Por Qué Usar Eventos?
-Los eventos te permiten separar diferentes partes de tu aplicación para que no dependan demasiado entre sí. Esta separación—frecuentemente llamada **desacoplamiento**—hace que tu código sea más fácil de actualizar, extender o depurar. En lugar de escribir todo en un solo bloque grande, puedes dividir tu lógica en piezas más pequeñas e independientes que responden a acciones específicas (eventos).
+Los eventos te permiten separar diferentes partes de tu aplicación para que no dependan demasiado entre sí. Esta separación—frecuentemente llamada **desacoplamiento**—hace que tu código sea más fácil de actualizar, extender o depurar. En lugar de escribir todo en un gran bloque, puedes dividir tu lógica en piezas más pequeñas e independientes que respondan a acciones específicas (eventos).
Imagina que estás construyendo una aplicación de blog:
- Cuando un usuario publica un comentario, podrías querer:
- Guardar el comentario en la base de datos.
- Enviar un correo electrónico al propietario del blog.
- - Registrar la acción por seguridad.
+ - Registrar la acción por razones de seguridad.
-Sin eventos, meterías todo esto en una sola función. Con eventos, puedes dividirlo: una parte guarda el comentario, otra activa un evento como `'comment.posted'`, y oyentes separados manejan el correo electrónico y el registro. Esto mantiene tu código más limpio y te permite agregar o eliminar características (como notificaciones) sin tocar la lógica central.
+Sin eventos, tendrías que meter todo esto en una sola función. Con eventos, puedes dividirlo: una parte guarda el comentario, otra activa un evento como `'comment.posted'`, y escuchas por separado manejan el correo electrónico y el registro. Esto mantiene tu código más limpio y te permite añadir o quitar características (como notificaciones) sin tocar la lógica central.
### Usos Comunes
-- **Registro**: Registra acciones como inicios de sesión o errores sin desordenar tu código principal.
-- **Notificaciones**: Envía correos electrónicos o alertas cuando algo sucede.
-- **Actualizaciones**: Actualiza cachés o notifica a otros sistemas sobre cambios.
+- **Registro**: Grabar acciones como inicios de sesión o errores sin desordenar tu código principal.
+- **Notificaciones**: Enviar correos electrónicos o alertas cuando ocurre algo.
+- **Actualizaciones**: Refrescar cachés o notificar a otros sistemas sobre cambios.
-## Registro de Oyentes de Eventos
+## Registrando Escuchadores de Eventos
-Para escuchar un evento, utiliza `Flight::onEvent()`. Este método te permite definir lo que debería suceder cuando un evento ocurre.
+Para escuchar un evento, utiliza `Flight::onEvent()`. Este método te permite definir qué debería suceder cuando ocurre un evento.
### Sintaxis
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Un nombre para tu evento (por ejemplo, `'user.login'`).
-- `$callback`: La función que se ejecutará cuando se active el evento.
+- `$event`: Un nombre para tu evento (ejemplo, `'user.login'`).
+- `$callback`: La función que se debe ejecutar cuando se activa el evento.
### Cómo Funciona
-"Te suscribes" a un evento diciéndole a Flight qué hacer cuando sucede. El callback puede aceptar argumentos que se pasan desde el disparador del evento.
+Te "suscribes" a un evento diciendo a Flight qué hacer cuando sucede. El callback puede aceptar argumentos pasados desde el disparador de eventos.
-El sistema de eventos de Flight es sincrónico, lo que significa que cada oyente de eventos se ejecuta en secuencia, uno tras otro. Cuando activas un evento, todos los oyentes registrados para ese evento se ejecutarán completamente antes de que tu código continúe. Esto es importante de entender, ya que difiere de los sistemas de eventos asincrónicos donde los oyentes pueden ejecutarse en paralelo o en un momento posterior.
+El sistema de eventos de Flight es sincrónico, lo que significa que cada escuchador de eventos se ejecuta en secuencia, uno tras otro. Cuando activas un evento, todos los escuchadores registrados para ese evento se ejecutarán hasta completarse antes de que tu código continúe. Esto es importante entender ya que difiere de los sistemas de eventos asincrónicos donde los escuchadores podrían ejecutarse en paralelo o en un momento posterior.
-### Ejemplo Sencillo
+### Ejemplo Simple
```php
Flight::onEvent('user.login', function ($username) {
echo "¡Bienvenido de nuevo, $username!";
@@ -46,105 +46,105 @@ Flight::onEvent('user.login', function ($username) {
Aquí, cuando se activa el evento `'user.login'`, saludará al usuario por su nombre.
### Puntos Clave
-- Puedes agregar múltiples oyentes al mismo evento: se ejecutarán en el orden en que los registraste.
-- El callback puede ser una función, una función anónima o un método de una clase.
+- Puedes añadir múltiples escuchadores al mismo evento; se ejecutarán en el orden en que los registraste.
+- El callback puede ser una función, una función anónima, o un método de una clase.
-## Activación de Eventos
+## Activando Eventos
-Para hacer que un evento suceda, utiliza `Flight::triggerEvent()`. Esto le dice a Flight que ejecute todos los oyentes registrados para ese evento, pasando cualquier dato que proporciones.
+Para hacer que un evento ocurra, utiliza `Flight::triggerEvent()`. Esto le dice a Flight que ejecute todos los escuchadores registrados para ese evento, pasando junto cualquier dato que proporciones.
### Sintaxis
```php
Flight::triggerEvent(string $event, ...$args): void
```
- `$event`: El nombre del evento que estás activando (debe coincidir con un evento registrado).
-- `...$args`: Argumentos opcionales para enviar a los oyentes (puede ser cualquier número de argumentos).
+- `...$args`: Argumentos opcionales para enviar a los escuchadores (pueden ser cualquier número de argumentos).
-### Ejemplo Sencillo
+### Ejemplo Simple
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Esto activa el evento `'user.login'` y envía `'alice'` al oyente que definimos anteriormente, que mostrará: `¡Bienvenido de nuevo, alice!`.
+Esto activa el evento `'user.login'` y envía `'alice'` al escuchador que definimos antes, que mostrará: `¡Bienvenido de nuevo, alice!`.
### Puntos Clave
-- Si no hay oyentes registrados, no sucede nada: tu aplicación no se romperá.
-- Utiliza el operador de expansión (`...`) para pasar múltiples argumentos de manera flexible.
+- Si no hay escuchadores registrados, no ocurre nada; tu aplicación no se romperá.
+- Usa el operador de expansión (`...`) para pasar múltiples argumentos de manera flexible.
-### Registro de Oyentes de Eventos
+### Registrando Escuchadores de Eventos
...
-**Deteniendo Oyentes Adicionales**:
-Si un oyente devuelve `false`, no se ejecutarán oyentes adicionales para ese evento. Esto te permite detener la cadena de eventos según condiciones específicas. Recuerda, el orden de los oyentes es importante, ya que el primero que devuelva `false` detendrá el resto.
+**Deteniendo Escuchadores Adicionales**:
+Si un escuchador devuelve `false`, no se ejecutarán más escuchadores para ese evento. Esto te permite detener la cadena de eventos basándote en condiciones específicas. Recuerda, el orden de los escuchadores importa, ya que el primero en devolver `false` detendrá al resto de ejecutarse.
**Ejemplo**:
```php
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // Detiene oyentes subsiguientes
+ return false; // Detiene los escuchadores posteriores.
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // esto nunca se envía
+ sendWelcomeEmail($username); // este nunca se enviará.
});
```
-## Sobrescribiendo Métodos de Eventos
+## Sobrescribiendo Métodos de Evento
-`Flight::onEvent()` y `Flight::triggerEvent()` están disponibles para ser [extendidos](/learn/extending), lo que significa que puedes redefinir cómo funcionan. Esto es excelente para usuarios avanzados que desean personalizar el sistema de eventos, como agregar registro o cambiar la forma en que se envían los eventos.
+`Flight::onEvent()` y `Flight::triggerEvent()` están disponibles para ser [extendidos](/learn/extending), lo que significa que puedes redefinir cómo funcionan. Esto es genial para usuarios avanzados que quieren personalizar el sistema de eventos, como añadir registro o cambiar cómo se despachan los eventos.
### Ejemplo: Personalizando `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
// Registra cada registro de evento
- error_log("Nuevo oyente de evento agregado para: $event");
- // Llama al comportamiento por defecto (asumiendo un sistema de eventos interno)
+ error_log("Nuevo escuchador de evento añadido para: $event");
+ // Llama al comportamiento predeterminado (suponiendo un sistema de eventos interno)
Flight::_onEvent($event, $callback);
});
```
Ahora, cada vez que registras un evento, se registra antes de continuar.
-### ¿Por qué sobrescribir?
-- Agregar depuración o monitoreo.
-- Restringir eventos en ciertos entornos (por ejemplo, deshabilitar en pruebas).
+### ¿Por Qué Sobrescribir?
+- Añadir depuración o monitoreo.
+- Restringir eventos en ciertos entornos (ejemplo, desactivar en pruebas).
- Integrar con una biblioteca de eventos diferente.
-## Dónde Colocar Tus Eventos
+## Dónde Poner Tus Eventos
-Como principiante, podrías preguntarte: *¿dónde registro todos estos eventos en mi aplicación?* La simplicidad de Flight significa que no hay reglas estrictas: puedes colocarlos donde tenga sentido para tu proyecto. Sin embargo, mantenerlos organizados te ayuda a mantener tu código a medida que tu aplicación crece. Aquí hay algunas opciones prácticas y mejores prácticas, adaptadas a la naturaleza ligera de Flight:
+Como principiante, podrías preguntarte: *¿dónde registro todos estos eventos en mi aplicación?* La simplicidad de Flight significa que no hay una regla estricta; puedes ponerlos donde tenga sentido para tu proyecto. Sin embargo, mantenerlos organizados te ayudará a mantener tu código a medida que tu aplicación crezca. Aquí tienes algunas opciones prácticas y mejores prácticas, adaptadas a la naturaleza ligera de Flight:
-### Opción 1: En tu `index.php` Principal
-Para aplicaciones pequeñas o prototipos rápidos, puedes registrar eventos directamente en tu archivo `index.php` junto a tus rutas. Esto mantiene todo en un solo lugar, lo cual está bien cuando la simplicidad es tu prioridad.
+### Opción 1: En Tu Archivo Principal `index.php`
+Para aplicaciones pequeñas o prototipos rápidos, puedes registrar eventos directamente en tu archivo `index.php` junto con tus rutas. Esto mantiene todo en un solo lugar, lo cual está bien cuando la simplicidad es tu prioridad.
```php
require 'vendor/autoload.php';
// Registrar eventos
Flight::onEvent('user.login', function ($username) {
- error_log("$username inició sesión en " . date('Y-m-d H:i:s'));
+ error_log("$username inició sesión a las " . date('Y-m-d H:i:s'));
});
// Definir rutas
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "¡Iniciado sesión!";
+ echo "¡Conectado!";
});
Flight::start();
```
-- **Pros**: Simple, sin archivos extra, excelente para proyectos pequeños.
+- **Pros**: Simple, sin archivos adicionales, excelente para proyectos pequeños.
- **Contras**: Puede volverse desordenado a medida que tu aplicación crece con más eventos y rutas.
### Opción 2: Un Archivo `events.php` Separado
-Para una aplicación ligeramente más grande, considera mover registros de eventos a un archivo dedicado como `app/config/events.php`. Incluye este archivo en tu `index.php` antes de tus rutas. Esto imita cómo a menudo se organizan las rutas en `app/config/routes.php` en proyectos de Flight.
+Para una aplicación un poco más grande, considera mover las registraciones de eventos a un archivo dedicado como `app/config/events.php`. Incluye este archivo en tu `index.php` antes de tus rutas. Esto imita cómo a menudo se organizan las rutas en `app/config/routes.php` en los proyectos de Flight.
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username inició sesión en " . date('Y-m-d H:i:s'));
+ error_log("$username inició sesión a las " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
@@ -160,39 +160,39 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "¡Iniciado sesión!";
+ echo "¡Conectado!";
});
Flight::start();
```
-- **Pros**: Mantiene `index.php` enfocado en el enrutamiento, organiza los eventos lógicamente, fácil de encontrar y editar.
-- **Contras**: Agrega un poco de estructura, lo que podría sentirse como excesivo para aplicaciones muy pequeñas.
+- **Pros**: Mantiene `index.php` enfocado en el enrutamiento, organiza eventos lógicamente, fácil de encontrar y editar.
+- **Contras**: Añade un poco de estructura, que podría parecer excesiva para aplicaciones muy pequeñas.
-### Opción 3: Cerca de Donde Son Activados
-Otro enfoque es registrar eventos cerca de donde son activados, como dentro de un controlador o definición de ruta. Esto funciona bien si un evento es específico de una parte de tu aplicación.
+### Opción 3: Cerca de Donde Se Activan
+Otro enfoque es registrar eventos cerca de donde se activan, como dentro de un controlador o definición de ruta. Esto funciona bien si un evento es específico de una parte de tu aplicación.
```php
Flight::route('/signup', function () {
// Registrar evento aquí
Flight::onEvent('user.registered', function ($email) {
- echo "Correo de bienvenida enviado a $email!";
+ echo "¡Correo de bienvenida enviado a $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "¡Registrado!";
+ echo "¡Te has registrado!";
});
```
-- **Pros**: Mantiene el código relacionado junto, bueno para características aisladas.
-- **Contras**: Dispersa los registros de eventos, dificultando ver todos los eventos a la vez; riesgo de registros duplicados si no se tiene cuidado.
+- **Pros**: Mantiene el código relacionado juntos, bueno para características aisladas.
+- **Contras**: Dispersa las registraciones de eventos, dificultando la visualización de todos los eventos a la vez; arriesga registros duplicados si no se tiene cuidado.
-### Mejores Prácticas para Flight
+### Mejor Práctica para Flight
- **Comienza Simple**: Para aplicaciones pequeñas, coloca eventos en `index.php`. Es rápido y se alinea con el minimalismo de Flight.
-- **Crecimiento Inteligente**: A medida que tu aplicación se expande (por ejemplo, más de 5-10 eventos), usa un archivo `app/config/events.php`. Es un paso natural hacia arriba, como organizar rutas, y mantiene tu código ordenado sin añadir marcos complejos.
-- **Evita la Sobrecarga de Ingeniería**: No crees una clase o directorio de "gestor de eventos" a menos que tu aplicación crezca enormemente: Flight prospera en la simplicidad, así que manténlo ligero.
+- **Crecimiento Inteligente**: A medida que tu aplicación se expande (por ejemplo, más de 5-10 eventos), utiliza un archivo `app/config/events.php`. Es un paso natural hacia arriba, como organizar rutas, y mantiene tu código ordenado sin añadir marcos complejos.
+- **Evita la Sobrecarga**: No crees una clase o directorio completo de "gestor de eventos" a menos que tu aplicación se vuelva enorme; Flight prospera en la simplicidad, así que manténlo ligero.
### Consejo: Agrupar por Propósito
-En `events.php`, agrupa eventos relacionados (por ejemplo, todos los eventos relacionados con usuarios juntos) con comentarios para claridad:
+En `events.php`, agrupa eventos relacionados (por ejemplo, todos los eventos relacionados con usuarios juntos) con comentarios para mayor claridad:
```php
// app/config/events.php
@@ -214,34 +214,34 @@ Esta estructura escala bien y se mantiene amigable para principiantes.
## Ejemplos para Principiantes
-Veamos algunos escenarios reales para mostrar cómo funcionan los eventos y por qué son útiles.
+Vamos a repasar algunos escenarios del mundo real para mostrar cómo funcionan los eventos y por qué son útiles.
-### Ejemplo 1: Registrando un Inicio de Sesión de Usuario
+### Ejemplo 1: Registro de un Inicio de Sesión de Usuario
```php
-// Paso 1: Registrar un oyente
+// Paso 1: Registrar un escuchador
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username inició sesión en $time");
+ error_log("$username inició sesión a las $time");
});
// Paso 2: Activarlo en tu aplicación
Flight::route('/login', function () {
- $username = 'bob'; // Suponiendo que esto proviene de un formulario
+ $username = 'bob'; // Supón que esto viene de un formulario
Flight::triggerEvent('user.login', $username);
echo "¡Hola, $username!";
});
```
-**Por qué es útil**: El código de inicio de sesión no necesita saber sobre el registro: simplemente activa el evento. Podrías agregar más oyentes más tarde (por ejemplo, enviar un correo de bienvenida) sin cambiar la ruta.
+**Por Qué Es Útil**: El código de inicio de sesión no necesita saber sobre el registro; simplemente activa el evento. Más tarde puedes añadir más escuchadores (por ejemplo, enviar un correo de bienvenida) sin cambiar la ruta.
-### Ejemplo 2: Notificando sobre Nuevos Usuarios
+### Ejemplo 2: Notificar Sobre Nuevos Usuarios
```php
-// Oyente para nuevos registros
+// Escuchador para nuevos registros
Flight::onEvent('user.registered', function ($email, $name) {
// Simular el envío de un correo electrónico
echo "Correo enviado a $email: ¡Bienvenido, $name!";
});
-// Activarlo cuando alguien se registre
+// Activarlo cuando alguien se registra
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
@@ -249,41 +249,47 @@ Flight::route('/signup', function () {
echo "¡Gracias por registrarte!";
});
```
-**Por qué es útil**: La lógica de registro se centra en crear al usuario, mientras que el evento maneja las notificaciones. Podrías agregar más oyentes (por ejemplo, registrar el registro) más tarde.
+**Por Qué Es Útil**: La lógica del registro se centra en crear al usuario, mientras que el evento maneja las notificaciones. Podrías añadir más escuchadores (por ejemplo, registrar la inscripción) más tarde.
-### Ejemplo 3: Limpiando una Caché
+### Ejemplo 3: Limpiando un Caché
```php
-// Oyente para limpiar una caché
+// Escuchador para limpiar un caché
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Limpiar caché de sesión si corresponde
+ unset($_SESSION['pages'][$pageId]); // Limpiar caché de sesión si es aplicable
echo "Caché limpiada para la página $pageId.";
});
// Activarlo cuando se edita una página
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Suponiendo que actualizamos la página
+ // Supón que actualizamos la página
Flight::triggerEvent('page.updated', $pageId);
echo "Página $pageId actualizada.";
});
```
-**Por qué es útil**: El código de edición no se preocupa por la caché: simplemente señala la actualización. Otras partes de la aplicación pueden reaccionar según sea necesario.
+**Por Qué Es Útil**: El código de edición no se preocupa por el caché; simplemente señala la actualización. Otras partes de la aplicación pueden reaccionar según sea necesario.
## Mejores Prácticas
-- **Nombra los eventos claramente**: Usa nombres específicos como `'user.login'` o `'page.updated'` para que sea evidente lo que hacen.
-- **Mantén los oyentes simples**: No pongas tareas lentas o complejas en los oyentes: mantén tu aplicación rápida.
-- **Prueba tus eventos**: Actívalos manualmente para asegurar que los oyentes funcionen como se espera.
-- **Usa eventos sabiamente**: Son excelentes para desacoplar, pero demasiados pueden complicar tu código: úsalos cuando tenga sentido.
+- **Nombra los Eventos Claramente**: Usa nombres específicos como `'user.login'` o `'page.updated'` para que sea obvio lo que hacen.
+- **Mantén los Escuchadores Simples**: No pongas tareas lentas o complejas en escuchadores; mantén tu aplicación rápida.
+- **Prueba Tus Eventos**: Actívalos manualmente para asegurar que los escuchadores funcionen como se espera.
+- **Usa Eventos de Manera Inteligente**: Son geniales para desacoplar, pero demasiados pueden hacer que tu código sea difícil de seguir; úsalos cuando tenga sentido.
-El sistema de eventos en Flight PHP, con `Flight::onEvent()` y `Flight::triggerEvent()`, te ofrece una forma simple pero poderosa de construir aplicaciones flexibles. Al permitir que diferentes partes de tu aplicación se comuniquen entre sí a través de eventos, puedes mantener tu código organizado, reutilizable y fácil de expandir. Ya sea que estés registrando acciones, enviando notificaciones o gestionando actualizaciones, los eventos te ayudan a hacerlo sin enredar tu lógica. Además, con la capacidad de sobrescribir estos métodos, tienes la libertad de adaptar el sistema a tus necesidades. Comienza con un solo evento y observa cómo transforma la estructura de tu aplicación.
+El sistema de eventos en Flight PHP, con `Flight::onEvent()` y `Flight::triggerEvent()`, te brinda una forma simple pero poderosa de construir aplicaciones flexibles. Al permitir que diferentes partes de tu aplicación se comuniquen entre sí a través de eventos, puedes mantener tu código organizado, reutilizable y fácil de expandir. Ya sea registrando acciones, enviando notificaciones o gestionando actualizaciones, los eventos te ayudan a hacerlo sin entrelazar tu lógica. Además, con la capacidad de sobrescribir estos métodos, tienes la libertad de adaptar el sistema a tus necesidades. Comienza con un evento único y observa cómo transforma la estructura de tu aplicación.
## Eventos Incorporados
-Flight PHP viene con algunos eventos incorporados que puedes usar para engancharte al ciclo de vida del marco. Estos eventos se activan en puntos específicos del ciclo de solicitud/respuesta, permitiéndote ejecutar lógica personalizada cuando ocurren ciertas acciones.
+Flight PHP viene con algunos eventos incorporados que puedes utilizar para engancharte al ciclo de vida del marco. Estos eventos se activan en puntos específicos del ciclo de solicitud/respuesta, lo que te permite ejecutar lógica personalizada cuando ocurren ciertas acciones.
### Lista de Eventos Incorporados
-- `flight.request.received`: Activado cuando se recibe, analiza y procesa una solicitud.
-- `flight.route.middleware.before`: Activado después de que se ejecute el middleware anterior.
-- `flight.route.middleware.after`: Activado después de que se ejecute el middleware posterior.
-- `flight.route.executed`: Activado después de que se ejecute y procese una ruta.
-- `flight.response.sent`: Activado después de que se envíe una respuesta al cliente.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` Se activa cuando se recibe, analiza y procesa una solicitud.
+- **flight.error**: `function(Throwable $exception)` Se activa cuando ocurre un error durante el ciclo de vida de la solicitud.
+- **flight.redirect**: `function(string $url, int $status_code)` Se activa cuando se inicia una redirección.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Se activa cuando se verifica la caché para una clave específica y si la caché fue un acierto o un fallo.
+- **flight.middleware.before**: `function(Route $route)` Se activa después de que se ejecuta el middleware anterior.
+- **flight.middleware.after**: `function(Route $route)` Se activa después de que se ejecuta el middleware posterior.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Se activa después de que se ejecuta cualquier middleware.
+- **flight.route.matched**: `function(Route $route)` Se activa cuando se coincide una ruta, pero aún no se ejecuta.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Se activa después de que se ejecuta y procesa una ruta. `$executionTime` es el tiempo que tomó ejecutar la ruta (llamar al controlador, etc.).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Se activa después de que se renderiza una vista. `$executionTime` es el tiempo que tomó renderizar la plantilla. **Nota: Si sobrescribes el método `render`, necesitarás volver a activar este evento.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Se activa después de que se envía una respuesta al cliente. `$executionTime` es el tiempo que tomó construir la respuesta.
\ No newline at end of file
diff --git a/content/v3/fr/awesome-plugins/apm.md b/content/v3/fr/awesome-plugins/apm.md
new file mode 100644
index 0000000..68d7ba0
--- /dev/null
+++ b/content/v3/fr/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# Documentation APM FlightPHP
+
+Bienvenue dans FlightPHP APM—le coach personnel de performance de 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 cherchiez des requêtes lentes ou que vous souhaitiez vous plonger dans des graphiques de latence, nous avons ce qu'il vous faut. Rendons votre application plus rapide, vos utilisateurs plus heureux et vos sessions de débogage plus simples !
+
+## Pourquoi l'APM est important
+
+Imaginez ceci : votre application est un restaurant occupé. Sans moyen de suivre combien de temps prennent les commandes ou où la cuisine est en difficulté, vous devinez pourquoi les clients partent de mauvaise humeur. 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 perdent des utilisateurs (des études disent que 53% abandonnent si un site met plus de 3 secondes à se charger !), et l'APM vous aide à attraper ces problèmes *avant* qu'ils ne fassent mal. C'est un esprit tranquille proactif—moins de moments "pourquoi cela ne fonctionne-t-il pas ?", plus de gains "regardez comme cela fonctionne bien !".
+
+## Installation
+
+Commencez avec Composer :
+
+```bash
+composer require flightphp/apm
+```
+
+Vous aurez besoin de :
+- **PHP 7.4+** : Garde notre compatibilité avec les distributions Linux LTS tout en prenant en charge PHP moderne.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+** : Le framework léger que nous renforçons.
+
+## Premiers pas
+
+Voici votre guide étape par étape vers l'incroyable APM :
+
+### 1. Enregistrez l'APM
+
+Ajoutez ceci dans votre `index.php` ou un fichier `services.php` pour commencer le suivi :
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Que se passe-t-il ici ?**
+- `LoggerFactory::create()` récupère votre configuration (plus à ce sujet 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 des métriques.
+- `bindEventsToFlightInstance($app)` lie le tout à votre application Flight.
+
+**Astuce pro : Échantillonnage**
+Si votre application est occupée, enregistrer *chaque* requête pourrait surcharger les choses. Utilisez un taux d'échantillonnage (0.0 à 1.0) :
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Enregistre 10% des requêtes
+```
+
+Cela garde la performance rapide tout en vous donnant des données solides.
+
+### 2. Configurez-le
+
+Exécutez ceci pour créer votre `.runway-config.json` :
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Que fait cela ?**
+- Lance un assistant demandant d'où proviennent les métriques brutes (source) et où vont les données traitées (destination).
+- Le défaut est SQLite—par exemple, `sqlite:/tmp/apm_metrics.sqlite` pour la source, une autre pour la destination.
+- Vous obtiendrez une configuration comme :
+ ```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"
+ }
+ }
+ ```
+
+**Pourquoi deux emplacements ?**
+Les métriques brutes s'accumulent rapidement (pensez aux journaux non filtrés). Le worker les traite en une destination structurée pour le tableau de bord. Cela garde les choses organisées !
+
+### 3. Traitez 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 :
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**Que fait-il ?**
+- Lit depuis votre source (par exemple, `apm_metrics.sqlite`).
+- Traite jusqu'à 100 métriques (taille de lot par défaut) vers votre destination.
+- S'arrête quand c'est fait ou s'il n'y a plus de métriques.
+
+**Gardez-le actif**
+Pour les applications en direct, vous voudrez un traitement continu. Voici vos options :
+
+- **Mode Daemon** :
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Fonctionne éternellement, 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 chaque minute—parfait pour la production.
+
+- **Tmux/Screen** :
+ Démarrez une session détachable :
+ ```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 se reconnecter
+ ```
+ Reste actif même si vous vous déconnectez.
+
+- **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` : 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 informations exploitables.
+
+### 4. Lancez le tableau de bord
+
+Voir les indicateurs de votre application :
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**Que fait cela ?**
+- Démarre un serveur PHP à `http://localhost:8001/apm/dashboard`.
+- Affiche les journaux de requêtes, les routes lentes, les taux d'erreurs, et plus encore.
+
+**Personnalisez-le** :
+```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).
+- `--port 8080` : Utilisez un port différent si 8001 est occupé.
+- `--php-path` : Pointe vers PHP si ce n'est pas dans votre PATH.
+
+Accédez à l'URL dans votre navigateur et explorez !
+
+#### Mode de 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-feux et d'autres mesures de sécurité en place. Voici quelques options :
+
+- **Utilisez un reverse proxy** : Configurez Nginx ou Apache pour faire suivre les requêtes au tableau de bord.
+- **Tunnel SSH** : Si vous pouvez SSH sur le serveur, utilisez `ssh -L 8080:localhost:8001 youruser@yourserver` pour tunneliser le tableau de bord sur 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 quel que soit le port que vous lui avez attribué).
+- **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 du document sur `/path/to/your/project/vendor/flightphp/apm/dashboard`
+
+#### Vous voulez un tableau de bord différent ?
+
+Vous pouvez construire votre propre tableau de bord si vous le souhaitez ! Consultez 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 QG APM—voici ce que vous verrez :
+
+- **Journal des requêtes** : Chaque requête avec horodatage, URL, code de réponse et temps total. Cliquez sur "Détails" pour middleware, requêtes et erreurs.
+- **Requêtes les plus lentes** : Les 5 requêtes prenant le plus de temps (par exemple, “/api/heavy” à 2.5s).
+- **Routes les plus lentes** : Les 5 routes par temps moyen—idéal pour repérer les schémas.
+- **Taux d'erreur** : Pourcentage de requêtes échouées (par exemple, 2.3% 500s).
+- **Percentiles de latence** : Temps de réponse 95e (p95) et 99e (p99)—connaître vos pires scénarios.
+- **Graphique des codes de réponse** : Visualisez les 200s, 404s, 500s au fil du temps.
+- **Requêtes/middleware longues** : Les 5 appels de base de données les plus lents et couches middleware.
+- **Cache Hit/Miss** : À quelle fréquence votre cache fait le travail.
+
+**Extras** :
+- Filtrez par "Dernière heure", "Dernier jour" ou "Dernière semaine".
+- Basculez en mode sombre pour les sessions tardives.
+
+**Exemple** :
+Une requête à `/users` pourrait montrer :
+- Temps total : 150ms
+- Middleware : `AuthMiddleware->handle` (50ms)
+- Requête : `SELECT * FROM users` (80ms)
+- Cache : Atteint sur `user_list` (5ms)
+
+## Ajout d'événements personnalisés
+
+Suivez tout—comme un appel API ou un processus de paiement :
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Où cela apparaît-il ?**
+Dans les détails de la requête du tableau de bord sous "Événements personnalisés"—développables avec un joli formatage JSON.
+
+**Cas d'utilisation** :
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Vous verrez maintenant si cette API ralentit votre application !
+
+## Surveillance de base de données
+
+Suivez les requêtes PDO comme ceci :
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Ce que vous obtenez** :
+- Texte de la requête (par exemple, `SELECT * FROM users WHERE id = ?`)
+- Temps d'exécution (par exemple, 0.015s)
+- Nombre de lignes (par exemple, 42)
+
+**Attention** :
+- **Optionnel** : Ignorez cela si vous n'avez pas besoin de suivi DB.
+- **PdoWrapper uniquement** : Le PDO de base n'est pas encore connecté—restez à l'écoute !
+- **Avertissement de performance** : Enregistrer chaque requête sur un site lourd en base de données 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`
+- Temps : 0.023s
+- Lignes : 15
+
+## Options de worker
+
+Ajustez le worker selon vos préférences :
+
+- `--timeout 300` : S'arrête après 5 minutes—idéal pour les tests.
+- `--max_messages 500` : Limite à 500 métriques—garde cela fini.
+- `--batch_size 200` : Traite 200 à la fois—équilibre vitesse et mémoire.
+- `--daemon` : Fonctionne sans arrêt—idéal pour la surveillance en direct.
+
+**Exemple** :
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+Fonctionne pendant une heure, traitant 100 métriques à la fois.
+
+## Résolution de problèmes
+
+Coincé ? Essayez ces éléments :
+
+- **Pas de données au tableau de bord ?**
+ - Le worker fonctionne-t-il ? Vérifiez `ps aux | grep apm:worker`.
+ - Les chemins de configuration correspondent-ils ? Vérifiez que les DSNs de `.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 de 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 des traces de pile.
+
+- **Le tableau de bord ne démarre pas ?**
+ - Le port 8001 est-il utilisé ? Utilisez `--port 8080`.
+ - PHP introuvable ? Utilisez `--php-path /usr/bin/php`.
+ - Pare-feu bloquant ? Ouvrez le port ou utilisez `--host localhost`.
+
+- **Trop lent ?**
+ - Abaissez le taux d'échantillonnage : `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Réduisez la taille du lot : `--batch_size 20`.
\ 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 7b34e56..85c4c30 100644
--- a/content/v3/fr/awesome-plugins/awesome_plugins.md
+++ b/content/v3/fr/awesome-plugins/awesome_plugins.md
@@ -4,32 +4,37 @@ Flight est incroyablement extensible. Il existe un certain nombre de plugins qui
## Documentation API
-La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce à quoi s'attendre en retour. Il existe quelques outils disponibles pour vous aider à générer de 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 à quoi s'attendre en retour. Il existe plusieurs 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 l'utilisation de la spécification OpenAPI avec FlightPHP pour construire votre API en utilisant une approche API first.
-- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer de 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.
+- [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 l'utilisation de la spécification OpenAPI avec FlightPHP pour développer 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 de la performance des applications (APM)
+
+La surveillance de la performance des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application fonctionne et où se trouvent les goulets d'étranglement. Il existe plusieurs outils APM qui peuvent être utilisés avec Flight.
+- beta[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 la performance de votre application et vous aider à identifier les goulets d'étranglement.
## Authentification/Autorisation
-L'authentification et l'autorisation sont cruciales pour toute application qui nécessite des contrôles en place sur qui peut accéder à quoi.
+L'authentification et l'autorisation 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 des autorisations Flight. Cette bibliothèque est un moyen simple d'ajouter des autorisations au niveau des utilisateurs et des applications à votre application.
+- official [flightphp/permissions](/awesome-plugins/permissions) - Bibliothèque officielle des permissions Flight. Cette bibliothèque est un moyen simple d'ajouter des permissions au niveau utilisateur et application à votre application.
## 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.
-- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP simple, légère et autonome dans le fichier.
+- official [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP légère, simple et autonome.
## 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.
-- officiel [flightphp/runway](/awesome-plugins/runway) - Runway est une application CLI qui vous aide à gérer vos applications Flight.
+- official [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 des petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences des utilisateurs, les paramètres de l'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 des préférences utilisateur, des paramètres d'application, et plus encore.
- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie est une bibliothèque PHP qui fournit un moyen simple et efficace de gérer les cookies.
@@ -37,43 +42,43 @@ Les cookies sont un excellent moyen de stocker des petites quantités de donnée
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 possède 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 a 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 au cœur de 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 sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORM complets.
-- officiel [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Wrapper PDO officiel de Flight qui fait partie du cœur. C'est un simple wrapper pour 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 de 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 garder une trace de tous les changements de base de données pour votre projet.
+- official [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Wrapper PDO Flight officiel qui fait partie du noyau. C'est un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution de requêtes. Ce n'est pas un ORM.
+- official [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.
+- [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre tous les changements 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 très 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. Commencer à la configurer 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 marche est assez simple pour commencer à chiffrer et déchiffrer des données.
-## File d'attente de tâches
+## File d'attente des tâches
-Les files d'attente de tâches sont très utiles pour traiter des tâches de manière asynchrone. Cela peut être l'envoi d'e-mails, le traitement d'images, ou tout ce qui n'a pas besoin d'être fait en temps réel.
+Les files d'attente des tâches sont très utiles pour traiter des 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 des 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 des emplois 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.
+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 de session officielle de Flight. 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 des sessions intégrée de PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de session PHP (non-bloquant, flash, segment, chiffrement de session). Utilise open_ssl de PHP pour le chiffrement/déchiffrement optionnel des données de session.
+- official [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle des sessions Flight. 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 des sessions 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 un chiffrement/déchiffrement optionnel des données de session.
-## Modèle
+## Modèles
-Le modèle est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modèles qui peuvent être utilisés avec Flight.
+Le modèle est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de templates qui peuvent être utilisés avec Flight.
-- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modèle 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èle complet qui est très facile à utiliser et se rapproche d'une syntaxe PHP par rapport à Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions.
+- deprecated [flightphp/core View](/learn#views) - C'est un moteur de templates très basique qui fait 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 templates complet qui est très facile à utiliser et qui semble plus proche d'une syntaxe PHP que Twig ou Smarty. C'est aussi très facile d'étendre et d'ajouter vos propres filtres et fonctions.
-## Contribuer
+## 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
diff --git a/content/v3/fr/awesome-plugins/tracy_extensions.md b/content/v3/fr/awesome-plugins/tracy_extensions.md
index 7f3b041..31079ae 100644
--- a/content/v3/fr/awesome-plugins/tracy_extensions.md
+++ b/content/v3/fr/awesome-plugins/tracy_extensions.md
@@ -4,29 +4,29 @@ Tracy Flight Panel Extensions
Il s'agit d'un ensemble d'extensions pour rendre le travail avec Flight un peu plus riche.
- Flight - Analyser toutes les variables de Flight.
-- Database - Analyser toutes les requêtes qui ont été exécutées sur la page (si vous initialisez correctement la connexion à la base de données).
-- Request - Analyser toutes les variables `$_SERVER` et examiner toutes les charges globales (`$_GET`, `$_POST`, `$_FILES`).
-- Session - Analyser toutes les variables `$_SESSION` si les sessions sont actives.
+- Database - Analyser toutes les requêtes qui ont été exécutées sur la page (si vous initiez correctement la connexion à la base de données)
+- Request - Analyser toutes les variables `$_SERVER` et examiner toutes les charges utiles globales (`$_GET`, `$_POST`, `$_FILES`)
+- Session - Analyser toutes les variables `$_SESSION` si des sessions sont actives.
-C'est le panneau
+Voici le panneau
-
+
Et chaque panneau affiche des informations très utiles sur votre application !
-
-
-
+
+
+
Cliquez [ici](https://github.com/flightphp/tracy-extensions) pour voir le code.
Installation
-------
-Exécutez `composer require flightphp/tracy-extensions --dev` et c'est parti !
+Exécutez `composer require flightphp/tracy-extensions --dev` et vous êtes en route !
Configuration
-------
-Il y a très peu de configuration à faire pour démarrer. Vous devrez initialiser le débogueur Tracy avant d'utiliser ceci [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Il y a très peu de configuration que vous devez faire pour commencer. Vous devrez initialiser le débogueur Tracy avant d'utiliser ceci [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide) :
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // Cela doit être faux sinon Tracy ne peut pas rendre correctement :(
+ // Cela doit être faux sinon Tracy ne peut pas réellement rendre :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -88,7 +89,7 @@ Flight::start();
### Latte
-Si vous avez Latte installé dans votre projet, vous pouvez utiliser le panneau Latte pour analyser vos modèles. Vous pouvez transmettre l'instance de Latte au constructeur `TracyExtensionLoader` avec la clé `latte` dans le deuxième paramètre.
+Si vous avez Latte installé dans votre projet, vous pouvez utiliser le panneau Latte pour analyser vos modèles. Vous pouvez passer l'instance Latte au constructeur de `TracyExtensionLoader` avec la clé `latte` dans le deuxième paramètre.
```php
@@ -106,7 +107,8 @@ $app->register('latte', Engine::class, [], function($latte) {
});
if(Debugger::$showBar === true) {
- // Cela doit être faux sinon Tracy ne peut pas rendre correctement :(
+ // Cela doit être faux sinon Tracy ne peut pas réellement rendre :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/fr/learn/events.md b/content/v3/fr/learn/events.md
index 7ece8b3..66c090b 100644
--- a/content/v3/fr/learn/events.md
+++ b/content/v3/fr/learn/events.md
@@ -1,57 +1,57 @@
# Système d'Événements dans Flight PHP (v3.15.0+)
-Flight PHP introduit un système d'événements léger et intuitif qui vous permet d'enregistrer et de déclencher des événements personnalisés dans votre application. Avec l'ajout de `Flight::onEvent()` et `Flight::triggerEvent()`, vous pouvez désormais vous intégrer aux moments clés du cycle de vie de votre application ou définir vos propres événements pour rendre votre code plus modulaire et extensible. Ces méthodes font partie des **méthodes mappables** de Flight, ce qui signifie que vous pouvez remplacer leur comportement pour l'adapter à vos besoins.
+Flight PHP introduit un système d'événements léger et intuitif qui vous permet d'enregistrer et de déclencher des événements personnalisés dans votre application. Avec l'ajout de `Flight::onEvent()` et `Flight::triggerEvent()`, vous pouvez désormais vous accrocher à des moments clés du cycle de vie de votre application ou définir vos propres événements pour rendre votre code plus modulaire et extensible. Ces méthodes font partie des **méthodes mappables** de Flight, ce qui signifie que vous pouvez remplacer leur comportement pour répondre à vos besoins.
Ce guide couvre tout ce que vous devez savoir pour commencer avec les événements, y compris pourquoi ils sont précieux, comment les utiliser, et des exemples pratiques pour aider les débutants à comprendre leur puissance.
## Pourquoi Utiliser des Événements ?
-Les événements vous permettent de séparer différentes parties de votre application afin qu'elles ne dépendent pas trop les unes des autres. Cette séparation—souvent appelée **découplage**—rend votre code plus facile à mettre à jour, à étendre ou à déboguer. Au lieu d'écrire tout dans un seul gros morceau, vous pouvez diviser votre logique en plus petits morceaux indépendants qui réagissent à des actions spécifiques (événements).
+Les événements vous permettent de séparer différentes parties de votre application afin qu'elles ne dépendent pas trop les unes des autres. Cette séparation—souvent appelée **découplage**—rend votre code plus facile à mettre à jour, à étendre ou à déboguer. Au lieu d'écrire tout dans un gros morceau, vous pouvez diviser votre logique en pièces plus petites et indépendantes qui réagissent à des actions spécifiques (événements).
Imaginez que vous construisez une application de blog :
-- Lorsqu'un utilisateur poste un commentaire, vous pourriez vouloir :
- - Enregistrer le commentaire dans la base de données.
+- Lorsqu'un utilisateur publie un commentaire, vous pourriez vouloir :
+ - Sauvegarder le commentaire dans la base de données.
- Envoyer un e-mail au propriétaire du blog.
- - Consigner l'action pour la sécurité.
+ - Journaliser l'action pour des raisons de sécurité.
-Sans événements, vous feriez tout cela dans une seule fonction. Avec des événements, vous pouvez le diviser : une partie enregistre le commentaire, une autre déclenche un événement comme `'comment.posted'`, et des écouteurs séparés gèrent l'e-mail et la journalisation. Cela maintient votre code plus propre et vous permet d'ajouter ou de supprimer des fonctionnalités (comme des notifications) sans toucher à la logique principale.
+Sans événements, vous entasseriez tout cela dans une seule fonction. Avec des événements, vous pouvez le diviser : une partie sauvegarde le commentaire, une autre déclenche un événement comme `'comment.posted'`, et des écouteurs séparés gèrent l'e-mail et la journalisation. Cela garde votre code plus propre et vous permet d'ajouter ou de supprimer des fonctionnalités (comme des notifications) sans toucher à la logique principale.
### Utilisations Courantes
- **Journalisation** : Enregistrer des actions comme des connexions ou des erreurs sans encombrer votre code principal.
-- **Notifications** : Envoyer des e-mails ou des alertes lorsque quelque chose se produit.
-- **Mises à jour** : Actualiser les caches ou notifier d'autres systèmes des changements.
+- **Notifications** : Envoyer des e-mails ou des alertes lorsqu'un événement se produit.
+- **Mises à jour** : Actualiser des caches ou informer d'autres systèmes des modifications.
-## Enregistrer des Écouteurs d'Événements
+## Enregistrement des Écouteurs d'Événements
-Pour écouter un événement, utilisez `Flight::onEvent()`. Cette méthode vous permet de définir ce qui doit se passer lorsqu'un événement se produit.
+Pour écouter un événement, utilisez `Flight::onEvent()`. Cette méthode vous permet de définir ce qui doit se produire lorsqu'un événement se produit.
### Syntaxe
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event` : Un nom pour votre événement (par exemple, `'user.login'`).
+- `$event` : Un nom pour votre événement (ex. : `'user.login'`).
- `$callback` : La fonction à exécuter lorsque l'événement est déclenché.
-### Comment Ça Fonctionne
-Vous "vous abonnez" à un événement en disant à Flight quoi faire quand il se produit. Le callback peut accepter des arguments passés depuis le déclencheur d'événements.
+### Comment Ça Marche
+Vous "vous abonnez" à un événement en disant à Flight ce qu'il doit faire lorsqu'il se produit. Le rappel peut accepter des arguments passés par le déclenchement de l'événement.
-Le système d'événements de Flight est synchrone, ce qui signifie que chaque écouteur d'événements est exécuté en séquence, l'un après l'autre. Lorsque vous déclenchez un événement, tous les écouteurs enregistrés pour cet événement s'exécuteront jusqu'à leur terme avant que votre code ne continue. Il est important de comprendre cela car cela diffère des systèmes d'événements asynchrones où les écouteurs peuvent s'exécuter en parallèle ou à un moment ultérieur.
+Le système d'événements de Flight est synchrone, ce qui signifie que chaque écouteur d'événement est exécuté en séquence, l'un après l'autre. Lorsque vous déclenchez un événement, tous les écouteurs enregistrés pour cet événement s'exécuteront jusqu'à leur achèvement avant que votre code ne continue. Il est important de comprendre cela car cela diffère des systèmes d'événements asynchrones où les écouteurs peuvent s'exécuter en parallèle ou à un moment ultérieur.
### Exemple Simple
```php
Flight::onEvent('user.login', function ($username) {
- echo "Bienvenue de nouveau, $username !";
+ echo "Bienvenue de nouveau, $username!";
});
```
-Ici, lorsque l'événement `'user.login'` est déclenché, il saluera l'utilisateur par son nom.
+Ici, lorsque l'événement `'user.login'` est déclenché, il accueillera l'utilisateur par son nom.
### Points Clés
-- Vous pouvez ajouter plusieurs écouteurs au même événement—ils s'exécuteront dans l'ordre où vous les avez enregistrés.
-- Le callback peut être une fonction, une fonction anonyme, ou une méthode d'une classe.
+- Vous pouvez ajouter plusieurs écouteurs au même événement ; ils s'exécuteront dans l'ordre où vous les avez enregistrés.
+- Le rappel peut être une fonction, une fonction anonyme ou une méthode d'une classe.
-## Déclenchement d'Événements
+## Déclenchement des Événements
-Pour faire se produire un événement, utilisez `Flight::triggerEvent()`. Cela demande à Flight d'exécuter tous les écouteurs enregistrés pour cet événement, en passant toute donnée que vous fournissez.
+Pour faire se produire un événement, utilisez `Flight::triggerEvent()`. Cela indique à Flight d'exécuter tous les écouteurs enregistrés pour cet événement, en passant toute donnée que vous fournissez.
### Syntaxe
```php
@@ -65,18 +65,18 @@ Flight::triggerEvent(string $event, ...$args): void
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Cela déclenche l'événement `'user.login'` et envoie `'alice'` à l'écouteur que nous avons défini plus tôt, qui produira : `Bienvenue de nouveau, alice !`.
+Cela déclenche l'événement `'user.login'` et envoie `'alice'` à l'écouteur que nous avons défini plus tôt, qui affichera : `Bienvenue de nouveau, alice!`.
### Points Clés
-- Si aucun écouteur n'est enregistré, rien ne se passe—votre application ne se brisera pas.
+- Si aucun écouteur n'est enregistré, rien ne se passe ; votre application ne planterait pas.
- Utilisez l'opérateur de propagation (`...`) pour passer plusieurs arguments de manière flexible.
-### Enregistrement d'Écouteurs d'Événements
+### Enregistrement des Écouteurs d'Événements
...
**Arrêter d'autres Écouteurs** :
-Si un écouteur renvoie `false`, aucun autre écouteur pour cet événement ne sera exécuté. Cela vous permet d'arrêter la chaîne d'événements en fonction de conditions spécifiques. Rappelez-vous, l'ordre des écouteurs est important, car le premier à renvoyer `false` arrêtera les autres de s'exécuter.
+Si un écouteur retourne `false`, aucun autre écouteur pour cet événement ne sera exécuté. Cela vous permet d'arrêter la chaîne d'événements en fonction de conditions spécifiques. Rappelez-vous, l'ordre des écouteurs est important, car le premier à retourner `false` arrêtera le reste.
**Exemple** :
```php
@@ -87,68 +87,68 @@ Flight::onEvent('user.login', function ($username) {
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // ceci n'est jamais envoyé
+ sendWelcomeEmail($username); // cela n'est jamais envoyé
});
```
-## Remplacer les Méthodes d'Événements
+## Surcharge des Méthodes d'Événements
-`Flight::onEvent()` et `Flight::triggerEvent()` sont disponibles pour être [étendus](/learn/extending), ce qui signifie que vous pouvez redéfinir leur fonctionnement. C'est formidable pour les utilisateurs avancés qui souhaitent personnaliser le système d'événements, comme ajouter des journaux ou changer la façon dont les événements sont dispatchés.
+`Flight::onEvent()` et `Flight::triggerEvent()` sont disponibles pour être [étendus](/learn/extending), ce qui signifie que vous pouvez redéfinir comment ils fonctionnent. C'est idéal pour les utilisateurs avancés qui souhaitent personnaliser le système d'événements, comme l'ajout de journalisation ou modifier la façon dont les événements sont dispatchés.
-### Exemple : Personnaliser `onEvent`
+### Exemple : Personnalisation de `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // Enregistrer chaque enregistrement d'événement
- error_log("Nouvel écouteur d'événement ajouté pour : $event");
+ // Journaliser chaque enregistrement d'événement
+ error_log("Nouveau listener d'événement ajouté pour : $event");
// Appeler le comportement par défaut (supposant un système d'événements interne)
Flight::_onEvent($event, $callback);
});
```
-Maintenant, chaque fois que vous enregistrez un événement, il l'enregistre avant de continuer.
+Maintenant, chaque fois que vous enregistrez un événement, il le journalise avant de continuer.
-### Pourquoi Remplacer ?
-- Ajouter du débogage ou de la surveillance.
-- Restreindre les événements dans certains environnements (par exemple, désactiver lors des tests).
+### Pourquoi Surcharger ?
+- Ajouter la journalisation ou le monitoring.
+- Restreindre les événements dans certains environnements (ex. : désactiver lors des tests).
- Intégrer une autre bibliothèque d'événements.
-## Où Mettre Vos Événements
+## Où Placer Vos Événements
-En tant que débutant, vous pourriez vous demander : *où dois-je enregistrer tous ces événements dans mon application ?* La simplicité de Flight signifie qu'il n'y a pas de règle stricte—vous pouvez les placer où cela a du sens pour votre projet. Cependant, les garder organisés vous aide à maintenir votre code à mesure que votre application grandit. Voici quelques options pratiques et meilleures pratiques, adaptées à la légèreté de Flight :
+En tant que débutant, vous vous demandez peut-être : *où enregistrer tous ces événements dans mon application ?* La simplicité de Flight signifie qu'il n'y a pas de règle stricte : vous pouvez les mettre où cela a du sens pour votre projet. Cependant, les garder organisés vous aide à maintenir votre code au fur et à mesure de la croissance de votre application. Voici quelques options pratiques et des meilleures pratiques, adaptées à la légèreté de Flight :
### Option 1 : Dans Votre Fichier Principal `index.php`
-Pour de petites applications ou des prototypes rapides, vous pouvez enregistrer des événements directement dans votre fichier `index.php` aux côtés de vos routes. Cela garde tout au même endroit, ce qui est bien lorsque la simplicité est votre priorité.
+Pour de petites applications ou des prototypes rapides, vous pouvez enregistrer des événements directement dans votre fichier `index.php` aux côtés de vos routes. Cela garde tout en un seul endroit, ce qui est acceptable lorsque la simplicité est votre priorité.
```php
require 'vendor/autoload.php';
// Enregistrer des événements
Flight::onEvent('user.login', function ($username) {
- error_log("$username s'est connecté à " . date('Y-m-d H:i:s'));
+ error_log("$username connecté à " . date('Y-m-d H:i:s'));
});
-// Définir des routes
+// Définir les routes
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Connecté !";
+ echo "Connecté!";
});
Flight::start();
```
- **Avantages** : Simple, pas de fichiers supplémentaires, idéal pour de petits projets.
-- **Inconvénients** : Peut devenir désordonné à mesure que votre application grandit avec plus d'événements et de routes.
+- **Inconvénients** : Peut devenir désordonné à mesure que votre application se développe avec plus d'événements et de routes.
### Option 2 : Un Fichier Séparé `events.php`
-Pour une application légèrement plus grande, envisagez de déplacer les enregistrements d'événements dans un fichier dédié comme `app/config/events.php`. Incluez ce fichier dans votre `index.php` avant vos routes. Cela imite la façon dont les routes sont souvent organisées dans `app/config/routes.php` dans les projets Flight.
+Pour une application un peu plus grande, envisagez de déplacer les enregistrements d'événements dans un fichier dédié comme `app/config/events.php`. Incluez ce fichier dans votre `index.php` avant vos routes. Cela imite comment les routes sont souvent organisées dans `app/config/routes.php` dans les projets Flight.
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username s'est connecté à " . date('Y-m-d H:i:s'));
+ error_log("$username connecté à " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
- echo "E-mail envoyé à $email : Bienvenue, $name !";
+ echo "E-mail envoyé à $email : Bienvenue, $name!";
});
```
@@ -160,48 +160,48 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Connecté !";
+ echo "Connecté!";
});
Flight::start();
```
-- **Avantages** : Garde `index.php` concentré sur le routage, organise les événements logiquement, facile à trouver et à éditer.
-- **Inconvénients** : Ajoute un peu de structure, ce qui pourrait sembler excessif pour des très petites applications.
+- **Avantages** : Garde `index.php` concentré sur le routage, organise les événements de manière logique, facile à trouver et à modifier.
+- **Inconvénients** : Ajoute un tout petit peu de structure, ce qui pourrait sembler excessif pour de très petites applications.
### Option 3 : Près de Leur Déclenchement
-Une autre approche consiste à enregistrer des événements près de leur déclenchement, comme à l'intérieur d'un contrôleur ou d'une définition de route. Cela fonctionne bien si un événement est spécifique à une partie de votre application.
+Une autre approche consiste à enregistrer les événements près de leur déclenchement, comme à l'intérieur d'un contrôleur ou d'une définition de route. Cela fonctionne bien si un événement est spécifique à une partie de votre application.
```php
Flight::route('/signup', function () {
// Enregistrer l'événement ici
Flight::onEvent('user.registered', function ($email) {
- echo "E-mail de bienvenue envoyé à $email !";
+ echo "E-mail de bienvenue envoyé à $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Inscrit !";
+ echo "Inscrit!";
});
```
- **Avantages** : Garde le code lié ensemble, bon pour des fonctionnalités isolées.
-- **Inconvénients** : Éparpille les enregistrements d'événements, rendant plus difficile la vue de tous les événements à la fois ; risque d'inscriptions en double si ce n'est pas prudent.
+- **Inconvénients** : Éparpille les enregistrements d'événements, ce qui rend plus difficile de voir tous les événements à la fois ; risque d'enregistrements en double si l'on n'y fait pas attention.
### Meilleure Pratique pour Flight
-- **Commencer Simple** : Pour de toutes petites applications, placez les événements dans `index.php`. C’est rapide et s'aligne sur le minimalisme de Flight.
-- **Grandir Intelligent** : À mesure que votre application s'élargit (par exemple, plus de 5-10 événements), utilisez un fichier `app/config/events.php`. C'est une étape naturelle, comme organiser des routes, et garde votre code bien rangé sans ajouter de frameworks complexes.
-- **Évitez la Sur-ingénierie** : Ne créez pas une classe ou un répertoire "gestionnaire d'événements" à moins que votre application ne devienne énorme—Flight prospère sur la simplicité, alors gardez-le léger.
+- **Commencez Simple** : Pour les petites applications, placez les événements dans `index.php`. C'est rapide et s'aligne avec le minimalisme de Flight.
+- **Croissez Intelligent** : À mesure que votre application s'agrandit (ex. : plus de 5-10 événements), utilisez un fichier `app/config/events.php`. C'est une étape logique, comme l'organisation des routes, et cela garde votre code propre sans ajouter de frameworks complexes.
+- **Évitez la Sur- Ingénierie** : Ne créez pas une classe ou un répertoire complet "gestionnaire d'événements" à moins que votre application ne devienne énorme—Flight prospère grâce à la simplicité, alors gardez-le léger.
-### Astuce : Groupez par Objectif
-Dans `events.php`, regroupez les événements liés (par exemple, tous les événements liés aux utilisateurs ensemble) avec des commentaires pour plus de clarté :
+### Conseil : Groupez par Objectif
+Dans `events.php`, groupez les événements connexes (ex. : tous les événements liés à l'utilisateur ensemble) avec des commentaires pour plus de clarté :
```php
// app/config/events.php
// Événements Utilisateur
Flight::onEvent('user.login', function ($username) {
- error_log("$username s'est connecté");
+ error_log("$username connecté");
});
Flight::onEvent('user.registered', function ($email) {
- echo "Bienvenue à $email !";
+ echo "Bienvenue à $email!";
});
// Événements de Page
@@ -210,80 +210,86 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-Cette structure évolue bien et reste conviviale pour les débutants.
+Cette structure se développe bien et reste conviviale pour les débutants.
-## Exemples pour les Débutants
+## Exemples pour Débutants
-Passons en revue quelques scénarios réels pour montrer comment les événements fonctionnent et pourquoi ils sont utiles.
+Passons en revue quelques scénarios du monde réel pour montrer comment les événements fonctionnent et pourquoi ils sont utiles.
### Exemple 1 : Journaliser une Connexion Utilisateur
```php
// Étape 1 : Enregistrer un écouteur
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username s'est connecté à $time");
+ error_log("$username connecté à $time");
});
// Étape 2 : Déclencher cela dans votre application
Flight::route('/login', function () {
$username = 'bob'; // Supposons que cela provienne d'un formulaire
Flight::triggerEvent('user.login', $username);
- echo "Salut, $username !";
+ echo "Salut, $username!";
});
```
-**Pourquoi C'est Utile** : Le code de connexion n'a pas besoin de se soucier de la journalisation—il déclenche juste l'événement. Vous pouvez plus tard ajouter plus d'écouteurs (par exemple, envoyer un e-mail de bienvenue) sans changer la route.
+**Pourquoi C'est Utile** : Le code de connexion n'a pas besoin de savoir sur la journalisation—il déclenche simplement l'événement. Vous pouvez plus tard ajouter d'autres écouteurs (ex. : envoyer un e-mail de bienvenue) sans changer la route.
### Exemple 2 : Notifier de Nouveaux Utilisateurs
```php
// Écouteur pour les nouvelles inscriptions
Flight::onEvent('user.registered', function ($email, $name) {
- // Simule l'envoi d'un e-mail
- echo "E-mail envoyé à $email : Bienvenue, $name !";
+ // Simuler l'envoi d'un e-mail
+ echo "E-mail envoyé à $email : Bienvenue, $name!";
});
-// Déclencher cela lorsque quelqu'un s'inscrit
+// Déclencher cela lors de l'inscription de quelqu'un
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "Merci pour votre inscription !";
+ echo "Merci pour votre inscription!";
});
```
-**Pourquoi C'est Utile** : La logique d'inscription se concentre sur la création de l'utilisateur, tandis que l'événement gère les notifications. Vous pourriez ajouter plus d'écouteurs (par exemple, journaliser l'inscription) plus tard.
+**Pourquoi C'est Utile** : La logique d'inscription se concentre sur la création de l'utilisateur, tandis que l'événement gère les notifications. Vous pourriez ajouter plus d'écouteurs (ex. : journaliser l'inscription) plus tard.
-### Exemple 3 : Vider un Cache
+### Exemple 3 : Effacer un Cache
```php
-// Écouteur pour vider un cache
+// Écouteur pour effacer un cache
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Vider le cache de session si applicable
- echo "Cache vidé pour la page $pageId.";
+ unset($_SESSION['pages'][$pageId]); // Effacer le cache de session si applicable
+ echo "Cache effacé pour la page $pageId.";
});
-// Déclencher lors de la modification d'une page
+// Déclencher lorsque la page est modifiée
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Supposons que nous ayons mis à jour la page
+ // Supposons que nous avons mis à jour la page
Flight::triggerEvent('page.updated', $pageId);
echo "Page $pageId mise à jour.";
});
```
-**Pourquoi C'est Utile** : Le code de modification ne se soucie pas du cache—il signale simplement la mise à jour. D'autres parties de l'application peuvent réagir selon leurs besoins.
+**Pourquoi C'est Utile** : Le code d'édition ne se préoccupe pas du cache—il signale simplement la mise à jour. D'autres parties de l'application peuvent réagir au besoin.
## Meilleures Pratiques
-- **Nommer les Événements Clairement** : Utilisez des noms spécifiques comme `'user.login'` ou `'page.updated'` pour qu'il soit évident ce qu'ils font.
-- **Garder les Écouteurs Simples** : Ne placez pas de tâches lentes ou complexes dans les écouteurs—gardez votre application rapide.
-- **Tester Vos Événements** : Déclenchez-les manuellement pour vous assurer que les écouteurs fonctionnent comme prévu.
-- **Utiliser les Événements Judicieusement** : Ils sont excellents pour le découplage, mais trop peuvent rendre votre code difficile à suivre—utilisez-les quand cela a du sens.
+- **Nommez les Événements Claire** : Utilisez des noms spécifiques comme `'user.login'` ou `'page.updated'` afin qu'il soit évident ce qu'ils font.
+- **Gardez les Écouteurs Simples** : Ne mettez pas de tâches lentes ou complexes dans les écouteurs—gardez votre application rapide.
+- **Testez Vos Événements** : Déclenchez-les manuellement pour vous assurer que les écouteurs fonctionnent comme prévu.
+- **Utilisez les Événements Judicieusement** : Ils sont excellents pour le découplage, mais trop peuvent rendre votre code difficile à suivre—utilisez-les lorsque cela a du sens.
-Le système d'événements dans Flight PHP, avec `Flight::onEvent()` et `Flight::triggerEvent()`, vous donne un moyen simple mais puissant de construire des applications flexibles. En laissant différentes parties de votre application communiquer entre elles par le biais d'événements, vous pouvez garder votre code organisé, réutilisable et facile à étendre. Que vous enregistriez des actions, envoyiez des notifications ou gériez des mises à jour, les événements vous aident à le faire sans enchevêtrer votre logique. De plus, avec la possibilité de remplacer ces méthodes, vous avez la liberté d'adapter le système à vos besoins. Commencez petit avec un seul événement, et regardez comment cela transforme la structure de votre application !
+Le système d'événements dans Flight PHP, avec `Flight::onEvent()` et `Flight::triggerEvent()`, vous offre une manière simple mais puissante de construire des applications flexibles. En permettant aux différentes parties de votre application de communiquer entre elles par le biais d'événements, vous pouvez garder votre code organisé, réutilisable et facile à étendre. Que vous journalisiez des actions, envoyiez des notifications ou gériez des mises à jour, les événements vous aident à le faire sans enlacer votre logique. De plus, avec la capacité de remplacer ces méthodes, vous avez la liberté de personnaliser le système selon vos besoins. Commencez petit avec un seul événement, et regardez comment cela transforme la structure de votre application !
## Événements Intégrés
-Flight PHP vient avec quelques événements intégrés que vous pouvez utiliser pour vous accrocher au cycle de vie du framework. Ces événements sont déclenchés à des moments spécifiques dans le cycle de demande/réponse, vous permettant d'exécuter une logique personnalisée lorsqu' certaines actions se produisent.
+Flight PHP propose quelques événements intégrés que vous pouvez utiliser pour vous accrocher à la lifecycle du framework. Ces événements sont déclenchés à des moments spécifiques dans le cycle requête/réponse, vous permettant d'exécuter une logique personnalisée lorsque certaines actions se produisent.
### Liste des Événements Intégrés
-- `flight.request.received` : Déclenché lorsqu'une demande est reçue, analysée et traitée.
-- `flight.route.middleware.before` : Déclenché après l'exécution du middleware avant.
-- `flight.route.middleware.after` : Déclenché après l'exécution du middleware après.
-- `flight.route.executed` : Déclenché après l'exécution et le traitement d'une route.
-- `flight.response.sent` : Déclenché après qu'une réponse a été envoyée au client.
\ No newline at end of file
+- **flight.request.received** : `function(Request $request)` Déclenché lorsqu'une requête est reçue, analysée et traitée.
+- **flight.error** : `function(Throwable $exception)` Déclenché lorsqu'une erreur se produit durant le cycle de vie de la requête.
+- **flight.redirect** : `function(string $url, int $status_code)` Déclenché lorsqu'une redirection est initiée.
+- **flight.cache.checked** : `function(string $cache_key, bool $hit, float $executionTime)` Déclenché lorsque le cache est vérifié pour une clé spécifique et si le cache a été atteint ou manqué.
+- **flight.middleware.before** : `function(Route $route)` Déclenché après l'exécution du middleware avant.
+- **flight.middleware.after** : `function(Route $route)` Déclenché après l'exécution du middleware après.
+- **flight.middleware.executed** : `function(Route $route, $middleware, string $method, float $executionTime)` Déclenché après l'exécution de tout middleware.
+- **flight.route.matched** : `function(Route $route)` Déclenché lorsqu'une route est correspondue, mais pas encore exécutée.
+- **flight.route.executed** : `function(Route $route, float $executionTime)` Déclenché après qu'une route soit exécutée et traitée. `$executionTime` est le temps qu'il a fallu pour exécuter la route (appeler le contrôleur, etc).
+- **flight.view.rendered** : `function(string $template_file_path, float $executionTime)` Déclenché après qu'une vue soit rendue. `$executionTime` est le temps qu'il a fallu pour rendre le modèle. **Remarque : Si vous remplacez la méthode `render`, vous devrez redéclencher cet événement.**
+- **flight.response.sent** : `function(Response $response, float $executionTime)` Déclenché après qu'une réponse soit envoyée au client. `$executionTime` est le temps qu'il a fallu pour construire la réponse.
\ No newline at end of file
diff --git a/content/v3/id/awesome-plugins/apm.md b/content/v3/id/awesome-plugins/apm.md
new file mode 100644
index 0000000..12a442b
--- /dev/null
+++ b/content/v3/id/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# Dokumentasi APM FlightPHP
+
+Selamat datang di APM FlightPHP—pelatih kinerja pribadi untuk 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 mengagumi grafik latensi, kami siap membantu. Mari kita buat aplikasi Anda lebih cepat, pengguna Anda lebih bahagia, dan sesi debugging Anda lebih mudah!
+
+## Mengapa APM Penting
+
+Bayangkan ini: aplikasi Anda adalah restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terhambat, Anda hanya menebak mengapa pelanggan meninggalkan tempat dengan kesal. APM adalah asisten koki Anda—ia mengawasi setiap langkah, mulai dari permintaan yang masuk hingga kueri basis data, dan menandai segala sesuatu yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (penelitian mengatakan 53% meninggalkan jika situs memerlukan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah itu *sebelum* mereka menjadi masalah. Ini memberi ketenangan pikiran yang proaktif—lebih sedikit “mengapa ini rusak?” momen, lebih banyak “lihat betapa lancarnya ini berfungsi!” kemenangan.
+
+## Instalasi
+
+Mulai dengan Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Anda akan membutuhkan:
+- **PHP 7.4+**: Memastikan kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP Modern.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka kerja ringan yang sedang kita tingkatkan.
+
+## Memulai
+
+Berikut adalah langkah demi langkah untuk kehebatan APM:
+
+### 1. Daftarkan APM
+
+Tambahkan ini ke dalam file `index.php` atau file `services.php` Anda untuk mulai melacak:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Apa yang terjadi di sini?**
+- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu segera) dan mengatur logger—SQLite secara default.
+- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik.
+- `bindEventsToFlightInstance($app)` mengaitkan semuanya ke aplikasi Flight Anda.
+
+**Tip Pro: Sampling**
+Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan laju sampel (0.0 hingga 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan
+```
+
+Ini menjaga kinerja tetap cepat sambil tetap memberikan data yang solid.
+
+### 2. Konfigurasikan
+
+Jalankan ini untuk membuat `.runway-config.json` Anda:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Apa yang dilakukan ini?**
+- Meluncurkan wizard yang menanyakan dari mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan).
+- Defaultnya adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, dan 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"
+ }
+ }
+ ```
+
+**Mengapa dua lokasi?**
+Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak difilter). Pekerja memprosesnya menjadi tujuan terstruktur untuk dasbor. Menjaga semuanya rapi!
+
+### 3. Proses Metrik dengan Pekerja
+
+Pekerja mengubah metrik mentah menjadi data 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 ketika selesai atau jika tidak ada metrik yang tersisa.
+
+**Jaga agar Tetap Berjalan**
+Untuk aplikasi langsung, Anda akan ingin pemrosesan yang berkelanjutan. Berikut adalah pilihan Anda:
+
+- **Mode Daemon**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Berjalan selamanya, memproses metrik saat mereka datang. Sangat baik untuk pengembangan atau pengaturan kecil.
+
+- **Crontab**:
+ Tambahkan ini ke crontab Anda (`crontab -e`):
+ ```bash
+ * * * * * php /path/to/project/vendor/bin/runway apm:worker
+ ```
+ Menyala setiap menit—sempurna untuk produksi.
+
+- **Tmux/Screen**:
+ Mulai sesi yang bisa dipisahkan:
+ ```bash
+ tmux new -s apm-worker
+ php vendor/bin/runway apm:worker --daemon
+ # Ctrl+B, lalu D untuk melepaskan; `tmux attach -t apm-worker` untuk terhubung kembali
+ ```
+ Menjaga agar tetap berjalan bahkan jika Anda log keluar.
+
+- **Penyesuaian Kustom**:
+ ```bash
+ php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
+ ```
+ - `--batch_size 50`: Memproses 50 metrik sekaligus.
+ - `--max_messages 1000`: Berhenti setelah 1000 metrik.
+ - `--timeout 300`: Keluar setelah 5 menit.
+
+**Mengapa repot?**
+Tanpa pekerja, 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 lainnya.
+
+**Kustomisasi**:
+```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 tampilan jarak jauh).
+- `--port 8080`: Gunakan port yang berbeda jika 8001 sudah terpakai.
+- `--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 ada kemungkinan firewall dan langkah-langkah keamanan lainnya. Berikut adalah beberapa opsi:
+
+- **Gunakan Proxy Terbalik**: 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 melakukan tunneling dasbor ke mesin lokal Anda.
+- **VPN**: Jika server Anda berada di belakang VPN, sambungkan 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 mengkonfigurasinya 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! Periksa direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri!
+
+## Fitur Dasbor
+
+Dasbor adalah markas APM Anda—berikut adalah yang akan Anda lihat:
+
+- **Log Permintaan**: Setiap permintaan dengan stempel waktu, URL, kode respons, dan total waktu. Klik "Detail" untuk middleware, kueri, dan kesalahan.
+- **Permintaan Ter Lambat**: 5 permintaan teratas yang memakan waktu (misalnya, “/api/heavy” dalam 2.5 detik).
+- **Rute Ter Lambat**: 5 rute teratas berdasarkan waktu rata-rata—baik untuk mengetahui pola.
+- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500).
+- **Persentil Latensi**: Waktu respons p95 (95th) dan p99 (99th)—ketahui skenario terburuk Anda.
+- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu.
+- **Kueri/Pemrograman Lambat**: 5 panggilan basis data dan lapisan middleware yang lambat.
+- **Cache Hit/Miss**: Seberapa sering cache Anda menolong.
+
+**Ekstra**:
+- Filter berdasarkan “Jam Terakhir,” “Hari Terakhir,” atau “Minggu Terakhir.”
+- Alihkan mode gelap untuk sesi larut malam.
+
+**Contoh**:
+Sebuah permintaan ke `/users` mungkin menunjukkan:
+- Total Waktu: 150ms
+- Middleware: `AuthMiddleware->handle` (50ms)
+- Kueri: `SELECT * FROM users` (80ms)
+- Cache: Hit pada `user_list` (5ms)
+
+## Menambahkan Acara Kustom
+
+Lacak apa pun—seperti panggilan API atau proses pembayaran:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Di mana ini muncul?**
+Di detail permintaan dasbor di bawah “Kegiatan Kustom”—dapat diperluas dengan format JSON yang rapi.
+
+**Kasus Penggunaan**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Sekarang Anda akan melihat apakah API tersebut memperlambat aplikasi Anda!
+
+## Pemantauan Basis Data
+
+Lacak kueri PDO seperti ini:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Apa yang Anda Dapatkan**:
+- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`)
+- Waktu eksekusi (misalnya, 0.015s)
+- Jumlah baris (misalnya, 42)
+
+**Perhatian**:
+- **Opsional**: Lewati ini jika Anda tidak memerlukan pelacakan DB.
+- **Hanya PdoWrapper**: Core PDO belum terhubung—nantikan!
+- **Peringatan Kinerja**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat segalanya. Gunakan sampling (`$Apm = new Apm($ApmLogger, 0.1)`) untuk mengurangi beban.
+
+**Contoh Output**:
+- Kueri: `SELECT name FROM products WHERE price > 100`
+- Waktu: 0.023s
+- Baris: 15
+
+## Opsi Pekerja
+
+Sesuaikan pekerja sesuai keinginan Anda:
+
+- `--timeout 300`: Berhenti setelah 5 menit—baik untuk pengujian.
+- `--max_messages 500`: Maksimal 500 metrik—menjaga agar tetap terbatas.
+- `--batch_size 200`: Memproses 200 sekaligus—seimbang antara kecepatan dan memori.
+- `--daemon`: Berjalan terus-menerus—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 pada satu waktu.
+
+## Pemecahan Masalah
+
+Terjebak? Coba ini:
+
+- **Tidak ada Data Dasbor?**
+ - Apakah pekerja sedang berjalan? Periksa `ps aux | grep apm:worker`.
+ - Apa jalur konfigurasi cocok? Verifikasi DSN `.runway-config.json` mengarah ke file yang nyata.
+ - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda.
+
+- **Kesalahan Pekerja?**
+ - 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 Mau Menyala?**
+ - Port 8001 digunakan? Gunakan `--port 8080`.
+ - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`.
+ - Firewall menghalangi? Buka port atau gunakan `--host localhost`.
+
+- **Terlalu Lambat?**
+ - Turunkan laju sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Kurangi ukuran batch: `--batch_size 20`.
\ 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 b3f5727..7bc5513 100644
--- a/content/v3/id/awesome-plugins/awesome_plugins.md
+++ b/content/v3/id/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
-# Plugin Luar Biasa
+# Plugin yang Menakjubkan
-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 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 lainnya 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.
+Dokumentasi API sangat penting untuk setiap API. Ini membantu pengembang memahami bagaimana 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) - Pos 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 hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan agar sesuai dengan 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) - Postingan blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API terlebih dahulu.
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat yang sangat baik untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan untuk memenuhi kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger.
+
+## Pemantauan Kinerja Aplikasi (APM)
+
+Pemantauan Kinerja Aplikasi (APM) sangat penting untuk setiap aplikasi. Ini membantu Anda memahami bagaimana kinerja aplikasi Anda dan di mana kendalanya. Ada sejumlah alat APM yang dapat digunakan dengan Flight.
+- beta[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 kendala.
## Autentikasi/Otorisasi
-Autentikasi dan Otorisasi sangat penting untuk setiap aplikasi yang memerlukan kontrol untuk siapa yang dapat mengakses apa.
+Autentikasi dan Otorisasi sangat penting untuk setiap aplikasi 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 Izin Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda.
## Cache
-Cache adalah cara yang bagus untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight.
+Cache adalah cara yang baik untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight.
-- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching PHP dalam file yang ringan, sederhana, dan mandiri.
+- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching PHP ringan, sederhana, dan mandiri dalam-file
## CLI
-Aplikasi CLI adalah cara yang bagus untuk berinteraksi dengan aplikasi Anda. Anda dapat menggunakannya untuk menghasilkan pengontrol, menampilkan semua rute, dan lainnya.
+Aplikasi CLI adalah cara yang baik untuk berinteraksi dengan aplikasi Anda. Anda dapat menggunakannya untuk menghasilkan pengontrol, menampilkan semua rute, dan banyak lagi.
- resmi [flightphp/runway](/awesome-plugins/runway) - Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda.
-## Cookies
+## Cookie
-Cookies adalah cara yang bagus untuk menyimpan sedikit data di sisi klien. Ini dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan lainnya.
+Cookie adalah cara yang baik untuk menyimpan sebagian kecil data 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.
+- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang memberikan cara sederhana dan efektif untuk mengelola cookie.
## Debugging
-Debugging sangat penting ketika Anda sedang 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 pengendali kesalahan dengan fitur lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda melakukan debug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri.
-- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan [Tracy](/awesome-plugins/tracy) pengendali kesalahan, plugin ini menambahkan beberapa panel ekstra untuk membantu dengan debugging khusus untuk proyek Flight.
+- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah pengelola kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda melakukan debugging aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan pengelola kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight.
## Basis Data
-Basis data adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpan dan mengambil data. Beberapa pustaka basis data hanyalah pembungkus untuk menulis kueri dan beberapa adalah ORM lengkap.
+Basis data adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka basis data hanya merupakan pembungkus untuk menulis kueri dan beberapa adalah ORM yang sepenuhnya berkembang.
-- resmi [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Pembungkus PDO resmi Flight yang merupakan bagian dari inti. Ini adalah pembungkus sederhana untuk membantu menyederhanakan proses menulis kueri dan mengeksekusinya. Ini bukan ORM.
+- resmi [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Pembungkus PDO resmi Flight 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/Pemetaan ActiveRecord resmi Flight. 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.
## Enkripsi
-Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenskripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [dapat](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 tidak pernah menyimpan kunci enkripsi Anda di direktori publik atau mengkomitnya ke repositori kode Anda.
+Enkripsi sangat penting untuk setiap aplikasi 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.) [sulit](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [dapat](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah tidak pernah menyimpan kunci enkripsi Anda di direktori publik atau menggunakannya dalam repositori kode Anda.
-- [defuse/php-encryption](/awesome-plugins/php-encryption) - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan berjalan cukup mudah untuk mulai mengenkripsi dan mendekripsi data.
+- [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 dapat berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara waktu nyata.
+Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apapun yang tidak perlu dilakukan secara waktu nyata.
- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Antrian Pekerjaan Sederhana adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL.
## Sesi
-Sesi tidak terlalu berguna untuk API, tetapi untuk membangun aplikasi web, sesi dapat sangat penting untuk memelihara status dan informasi login.
+Sesi tidak terlalu berguna untuk API, tetapi untuk membangun aplikasi web, sesi dapat menjadi sangat penting untuk mempertahankan status dan informasi login.
- resmi [flightphp/session](/awesome-plugins/session) - Pustaka Sesi resmi Flight. 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) - Pengelola Sesi PHP (non-blocking, flash, segment, enkripsi sesi). Menggunakan open_ssl PHP untuk enkripsi/dekripsi opsional data sesi.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - Pengelola Sesi PHP (non-blokir, flash, segmen, enkripsi sesi). Menggunakan PHP open_ssl untuk enkripsi/dekripsi sesi data secara opsional.
## Templating
-Templating adalah inti dari setiap aplikasi web dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight.
+Templating adalah inti dari setiap aplikasi web dengan antarmuka pengguna. Ada sejumlah mesin templating yang dapat digunakan dengan Flight.
-- ditinggalkan [flightphp/core View](/learn#views) - Ini adalah mesin templating yang sangat dasar yang merupakan bagian dari inti. Ini tidak dianjurkan digunakan jika Anda memiliki lebih dari beberapa halaman dalam proyek Anda.
-- [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating dengan fitur lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP dibandingkan Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter serta fungsi Anda sendiri.
+- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating yang sangat dasar yang merupakan bagian dari inti. Tidak disarankan untuk digunakan jika Anda memiliki lebih dari beberapa halaman dalam proyek Anda.
+- [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP dibandingkan Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri.
-## Kontribusi
+## Berkontribusi
-Apakah Anda memiliki plugin yang ingin Anda bagikan? Kirim permohonan tarik untuk menambahkannya ke daftar!
\ No newline at end of file
+Punya plugin yang ingin Anda bagikan? Kirim permintaan tarik untuk menambahkannya ke daftar!
\ No newline at end of file
diff --git a/content/v3/id/awesome-plugins/tracy_extensions.md b/content/v3/id/awesome-plugins/tracy_extensions.md
index 7b56953..8a56168 100644
--- a/content/v3/id/awesome-plugins/tracy_extensions.md
+++ b/content/v3/id/awesome-plugins/tracy_extensions.md
@@ -1,10 +1,10 @@
Tracy Flight Panel Extensions
=====
-Ini adalah serangkaian ekstensi untuk membuat kerja dengan Flight sedikit lebih kaya.
+Ini adalah seperangkat ekstensi untuk membuat kerja dengan Flight sedikit lebih kaya.
- Flight - Analisis semua variabel Flight.
-- Database - Analisis semua kueri yang telah dijalankan di halaman (jika Anda benar-benar memulai koneksi database)
+- Database - Analisis semua kueri yang telah dijalankan di halaman (jika Anda telah memulai koneksi database dengan benar)
- Request - Analisis semua variabel `$_SERVER` dan periksa semua payload global (`$_GET`, `$_POST`, `$_FILES`)
- Session - Analisis semua variabel `$_SESSION` jika sesi aktif.
@@ -18,7 +18,7 @@ Dan setiap panel menampilkan informasi yang sangat berguna tentang aplikasi Anda


-Klik [di sini](https://github.com/flightphp/tracy-extensions) untuk melihat kode.
+Klik [di sini](https://github.com/flightphp/tracy-extensions) untuk melihat kodenya.
Instalasi
-------
@@ -40,22 +40,22 @@ require __DIR__ . '/vendor/autoload.php';
Debugger::enable();
// Anda mungkin perlu menentukan lingkungan Anda dengan Debugger::enable(Debugger::DEVELOPMENT)
-// jika Anda menggunakan koneksi database dalam aplikasi Anda, ada
+// jika Anda menggunakan koneksi database di aplikasi Anda, ada
// pembungkus PDO yang diperlukan untuk digunakan HANYA DI PENGEMBANGAN (bukan produksi, tolong!)
// Ini memiliki parameter yang sama dengan koneksi PDO biasa
$pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass');
-// atau jika Anda melampirkan ini ke framework Flight
+// atau jika Anda menambahkannya ke framework Flight
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']);
-// sekarang setiap kali Anda melakukan kueri, akan menangkap waktu, kueri, dan parameter
+// sekarang setiap kali Anda melakukan kueri, itu akan menangkap waktu, kueri, dan parameter
// Ini menghubungkan titik-titik
if(Debugger::$showBar === true) {
- // Ini perlu false atau Tracy tidak bisa benar-benar merender :(
+ // Ini perlu false atau Tracy tidak dapat merender :)
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
-// lebih banyak kode
+// kode lebih lanjut
Flight::start();
```
@@ -63,11 +63,12 @@ Flight::start();
## Konfigurasi Tambahan
### Data Sesi
-Jika Anda memiliki pengendali sesi kustom (seperti ghostff/session), Anda dapat meneruskan array data sesi apa pun ke Tracy dan secara otomatis akan mengeluarkannya untuk Anda. Anda mengirimkannya dengan kunci `session_data` di parameter kedua konstruktor `TracyExtensionLoader`.
+Jika Anda memiliki pengelola sesi kustom (seperti ghostff/session), Anda dapat mengirimkan array data sesi apa pun ke Tracy dan itu secara otomatis akan mengeluarkannya untuk Anda. Anda mengirimkannya dengan kunci `session_data` di parameter kedua dari konstruktor `TracyExtensionLoader`.
```php
use Ghostff\Session\Session;
+// atau gunakan flight\Session;
require 'vendor/autoload.php';
@@ -76,19 +77,19 @@ $app = Flight::app();
$app->register('session', Session::class);
if(Debugger::$showBar === true) {
- // Ini perlu false atau Tracy tidak bisa benar-benar merender :(
+ // Ini perlu false atau Tracy tidak dapat merender :)
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
-// rute dan hal-hal lain...
+// rute dan hal-hal lainnya...
Flight::start();
```
### Latte
-Jika Anda telah menginstal Latte di proyek Anda, Anda dapat menggunakan panel Latte untuk menganalisis template Anda. Anda dapat meneruskan instance Latte ke konstruktor `TracyExtensionLoader` dengan kunci `latte` di parameter kedua.
+Jika Anda memiliki Latte terinstal di proyek Anda, Anda dapat menggunakan panel Latte untuk menganalisis template Anda. Anda dapat mengirimkan instance Latte ke konstruktor `TracyExtensionLoader` dengan kunci `latte` di parameter kedua.
```php
@@ -106,7 +107,7 @@ $app->register('latte', Engine::class, [], function($latte) {
});
if(Debugger::$showBar === true) {
- // Ini perlu false atau Tracy tidak bisa benar-benar merender :(
+ // Ini perlu false atau Tracy tidak dapat merender :)
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
diff --git a/content/v3/id/learn/events.md b/content/v3/id/learn/events.md
index 021fd8a..8734e91 100644
--- a/content/v3/id/learn/events.md
+++ b/content/v3/id/learn/events.md
@@ -1,41 +1,41 @@
# Sistem Acara di Flight PHP (v3.15.0+)
-Flight PHP memperkenalkan sistem acara yang ringan dan intuitif yang memungkinkan Anda mendaftar dan memicu acara kustom di aplikasi Anda. Dengan penambahan `Flight::onEvent()` dan `Flight::triggerEvent()`, Anda sekarang dapat terhubung ke momen-momen penting dalam siklus hidup aplikasi Anda atau mendefinisikan acara Anda sendiri untuk membuat kode Anda lebih modular dan dapat diperluas. Metode ini adalah bagian dari **metode yang dapat dipetakan** Flight, yang berarti Anda dapat mengganti perilaku mereka sesuai dengan kebutuhan Anda.
+Flight PHP memperkenalkan sistem acara yang ringan dan intuitif yang memungkinkan Anda mendaftarkan dan memicu acara kustom dalam aplikasi Anda. Dengan penambahan `Flight::onEvent()` dan `Flight::triggerEvent()`, Anda sekarang dapat terhubung dengan momen kunci dari siklus hidup aplikasi Anda atau mendefinisikan acara Anda sendiri untuk membuat kode Anda lebih modular dan dapat diperluas. Metode-metode ini adalah bagian dari **metode yang dapat dipetakan** di Flight, yang berarti Anda dapat mengganti perilakunya untuk memenuhi kebutuhan Anda.
-Panduan ini mencakup semuanya yang perlu Anda ketahui untuk memulai dengan acara, termasuk mengapa mereka berharga, bagaimana cara menggunakannya, dan contoh praktis untuk membantu pemula memahami kekuatannya.
+Panduan ini mencakup semua yang Anda perlu ketahui untuk memulai dengan acara, termasuk mengapa acara itu berharga, cara menggunakannya, dan contoh praktis untuk membantu pemula memahami kekuatannya.
## Mengapa Menggunakan Acara?
-Acara memungkinkan Anda untuk memisahkan bagian-bagian berbeda dari aplikasi Anda sehingga mereka tidak terlalu bergantung satu sama lain. Pemisahan ini—sering disebut **decoupling**—memudahkan kode Anda untuk diperbarui, diperluas, atau di-debug. Alih-alih menulis semuanya dalam satu blok besar, Anda dapat memecah logika Anda menjadi potongan-potongan kecil yang independen yang merespons tindakan spesifik (acara).
+Acara memungkinkan Anda untuk memisahkan berbagai bagian dari aplikasi Anda sehingga mereka tidak tergantung satu sama lain secara berlebihan. Pemisahan ini—sering disebut **decoupling**—mempermudah kode Anda untuk diperbarui, diperluas, atau debuggé. Alih-alih menulis semuanya dalam satu bagian besar, Anda dapat membagi logika Anda menjadi bagian yang lebih kecil dan independen yang merespons tindakan tertentu (acara).
Bayangkan Anda sedang membangun aplikasi blog:
-- Ketika seorang pengguna mengirimkan komentar, Anda mungkin ingin:
- - Menyimpan komentar ke dalam basis data.
- - Mengirim email kepada pemilik blog.
- - Mencatat tindakan untuk keamanan.
+- Ketika seorang pengguna mengirim komentar, Anda mungkin ingin:
+ - Menyimpan komentar ke database.
+ - Mengirim email ke pemilik blog.
+ - Mencatat aksi untuk keamanan.
-Tanpa acara, Anda akan memasukkan semua ini ke dalam satu fungsi. Dengan acara, Anda dapat memecahnya: satu bagian menyimpan komentar, bagian lain memicu acara seperti `'comment.posted'`, dan pendengar terpisah menangani email dan pencatatan. Ini menjaga kode Anda lebih bersih dan memungkinkan Anda menambah atau menghapus fitur (seperti notifikasi) tanpa menyentuh logika inti.
+Tanpa acara, Anda akan menggabungkan semua ini menjadi satu fungsi. Dengan acara, Anda dapat membaginya: satu bagian menyimpan komentar, bagian lain memicu acara seperti `'comment.posted'`, dan pendengar terpisah menangani email dan pencatatan. Ini menjaga kode Anda lebih bersih dan memungkinkan Anda menambah atau menghapus fitur (seperti notifikasi) tanpa mengganggu logika inti.
### Penggunaan Umum
-- **Pencatatan**: Mencatat tindakan seperti login atau kesalahan tanpa mengacaukan kode utama Anda.
+- **Pencatatan**: Mencatat aksi seperti login atau kesalahan tanpa mengotori kode utama Anda.
- **Notifikasi**: Mengirim email atau peringatan ketika sesuatu terjadi.
- **Pembaruan**: Menyegarkan cache atau memberi tahu sistem lain tentang perubahan.
-## Mendaftar Pendengar Acara
+## Mendaftarkan Pendengar Acara
-Untuk mendengarkan sebuah acara, gunakan `Flight::onEvent()`. Metode ini memungkinkan Anda menentukan apa yang harus terjadi ketika sebuah acara terjadi.
+Untuk mendengarkan sebuah acara, gunakan `Flight::onEvent()`. Metode ini memungkinkan Anda mendefinisikan apa yang harus dilakukan ketika sebuah acara terjadi.
### Sintaks
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Nama untuk acara Anda (misalnya, `'user.login'`).
+- `$event`: Sebuah nama untuk acara Anda (misalnya, `'user.login'`).
- `$callback`: Fungsi yang dijalankan ketika acara dipicu.
### Cara Kerjanya
-Anda "berlangganan" ke sebuah acara dengan memberi tahu Flight apa yang harus dilakukan ketika acara itu terjadi. Callback dapat menerima argumen yang diteruskan dari pemicu acara.
+Anda "berlangganan" ke sebuah acara dengan memberi tahu Flight apa yang harus dilakukan ketika acara itu terjadi. Callback dapat menerima argumen yang dikirim dari pemicu acara.
-Sistem acara Flight bersifat sinkron, yang berarti setiap pendengar acara dieksekusi secara berurutan, satu setelah yang lain. Ketika Anda memicu sebuah acara, semua pendengar terdaftar untuk acara itu akan dijalankan hingga selesai sebelum kode Anda dilanjutkan. Ini penting untuk dipahami karena berbeda dari sistem acara asinkron di mana pendengar mungkin dijalankan secara paralel atau pada waktu yang lebih lambat.
+Sistem acara di Flight bersifat sinkron, yang berarti setiap pendengar acara dieksekusi secara berurutan, satu setelah yang lain. Ketika Anda memicu sebuah acara, semua pendengar yang terdaftar untuk acara tersebut akan dijalankan hingga selesai sebelum kode Anda melanjutkan. Ini penting untuk dipahami karena berbeda dengan sistem acara asinkron di mana pendengar mungkin dijalankan secara paralel atau pada waktu yang lebih lambat.
### Contoh Sederhana
```php
@@ -43,11 +43,11 @@ Flight::onEvent('user.login', function ($username) {
echo "Selamat datang kembali, $username!";
});
```
-Di sini, ketika acara `'user.login'` dipicu, ia akan menyapa pengguna dengan nama.
+Di sini, ketika acara `'user.login'` dipicu, itu akan menyapa pengguna dengan namanya.
-### Poin Utama
-- Anda dapat menambahkan beberapa pendengar ke acara yang sama—mereka akan dijalankan dalam urutan Anda mendaftarkannya.
-- Callback dapat berupa fungsi, fungsi anonim, atau metode dari sebuah kelas.
+### Poin Penting
+- Anda dapat menambahkan beberapa pendengar untuk acara yang sama—mereka akan dijalankan dalam urutan Anda mendaftarkannya.
+- Callback bisa berupa fungsi, fungsi anonim, atau metode dari sebuah kelas.
## Memicu Acara
@@ -57,26 +57,26 @@ Untuk membuat sebuah acara terjadi, gunakan `Flight::triggerEvent()`. Ini member
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: Nama acara yang Anda picu (harus cocok dengan acara terdaftar).
-- `...$args`: Argumen opsional untuk dikirim ke pendengar (dapat berupa jumlah argumen apa pun).
+- `$event`: Nama acara yang Anda picu (harus cocok dengan acara yang terdaftar).
+- `...$args`: Argumen opsional untuk dikirim ke pendengar (dapat berupa jumlah argumen berapa pun).
### Contoh Sederhana
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Ini memicu acara `'user.login'` dan mengirimkan `'alice'` kepada pendengar yang telah kita definisikan sebelumnya, yang akan menghasilkan: `Selamat datang kembali, alice!`.
+Ini memicu acara `'user.login'` dan mengirimkan `'alice'` ke pendengar yang telah kita definisikan sebelumnya, yang akan menghasilkan output: `Selamat datang kembali, alice!`.
-### Poin Utama
+### Poin Penting
- Jika tidak ada pendengar yang terdaftar, tidak ada yang terjadi—aplikasi Anda tidak akan rusak.
- Gunakan operator spread (`...`) untuk meneruskan beberapa argumen dengan fleksibel.
-### Mendaftar Pendengar Acara
+### Mendaftarkan Pendengar Acara
...
-**Menghentikan Pendengar Selanjutnya**:
-Jika sebuah pendengar mengembalikan `false`, pendengar tambahan untuk acara itu tidak akan dieksekusi. Ini memungkinkan Anda untuk menghentikan rantai acara berdasarkan kondisi tertentu. Ingat, urutan pendengar itu penting, karena pendengar pertama yang mengembalikan `false` akan menghentikan yang lainnya dari berjalan.
+**Menghentikan Pendengar Lebih Lanjut**:
+Jika sebuah pendengar mengembalikan `false`, tidak ada pendengar tambahan untuk acara tersebut yang akan dieksekusi. Ini memungkinkan Anda untuk menghentikan rantai acara berdasarkan kondisi tertentu. Ingat, urutan pendengar itu penting, karena yang pertama mengembalikan `false` akan menghentikan sisanya dari menjalankan.
**Contoh**:
```php
@@ -93,30 +93,30 @@ Flight::onEvent('user.login', function ($username) {
## Mengganti Metode Acara
-`Flight::onEvent()` dan `Flight::triggerEvent()` tersedia untuk [diperluas](/learn/extending), yang berarti Anda dapat mendefinisikan ulang bagaimana mereka bekerja. Ini sangat baik untuk pengguna tingkat lanjut yang ingin menyesuaikan sistem acara, seperti menambahkan pencatatan atau mengubah cara acara dikirimkan.
+`Flight::onEvent()` dan `Flight::triggerEvent()` tersedia untuk [diperluas](/learn/extending), yang berarti Anda dapat mendefinisikan ulang bagaimana cara kerjanya. Ini sangat bagus untuk pengguna tingkat lanjut yang ingin menyesuaikan sistem acara, seperti menambahkan pencatatan atau mengubah cara acara dikirim.
### Contoh: Menyesuaikan `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
// Mencatat setiap pendaftaran acara
error_log("Pendengar acara baru ditambahkan untuk: $event");
- // Panggil perilaku default (mengasumsikan ada sistem acara internal)
+ // Panggil perilaku default (dengan asumsi ada sistem acara internal)
Flight::_onEvent($event, $callback);
});
```
-Sekarang, setiap kali Anda mendaftarkan sebuah acara, ia akan mencatatnya sebelum melanjutkan.
+Sekarang, setiap kali Anda mendaftarkan sebuah acara, itu mencatatnya sebelum melanjutkan.
### Mengapa Mengganti?
- Menambahkan debugging atau pemantauan.
-- Membatasi acara di lingkungan tertentu (misalnya, menonaktifkan saat pengujian).
-- Mengintegrasikan dengan pustaka acara yang berbeda.
+- Membatasi acara dalam lingkungan tertentu (misalnya, menonaktifkan dalam pengujian).
+- Mengintegrasikan dengan perpustakaan acara yang berbeda.
## Di Mana Menempatkan Acara Anda
-Sebagai pemula, Anda mungkin bertanya: *di mana saya mendaftarkan semua acara ini di aplikasi saya?* Kesederhanaan Flight berarti tidak ada aturan ketat—Anda dapat menempatkannya di mana pun terasa tepat untuk proyek Anda. Namun, menjaga mereka terorganisir membantu Anda mempertahankan kode Anda seiring pertumbuhan aplikasi Anda. Berikut adalah beberapa opsi praktis dan praktik terbaik, disesuaikan dengan sifat ringan Flight:
+Sebagai pemula, Anda mungkin bertanya: *di mana saya mendaftarkan semua acara ini dalam aplikasi saya?* Kesederhanaan Flight berarti tidak ada aturan ketat—Anda dapat menempatkannya di mana pun yang masuk akal untuk proyek Anda. Namun, menjaga mereka terorganisir membantu Anda memelihara kode Anda seiring pertumbuhan aplikasi Anda. Berikut beberapa opsi praktis dan praktik terbaik, disesuaikan dengan sifat ringan Flight:
### Opsi 1: Di `index.php` Utama Anda
-Untuk aplikasi kecil atau prototipe cepat, Anda dapat mendaftarkan acara langsung di file `index.php` Anda bersamaan dengan rute Anda. Ini menjaga semuanya di satu tempat, yang baik ketika kesederhanaan adalah prioritas Anda.
+Untuk aplikasi kecil atau prototipe cepat, Anda dapat mendaftarkan acara langsung di file `index.php` Anda bersama dengan jalur Anda. Ini menjaga segala sesuatunya dalam satu tempat, yang baik ketika kesederhanaan adalah prioritas Anda.
```php
require 'vendor/autoload.php';
@@ -126,20 +126,20 @@ Flight::onEvent('user.login', function ($username) {
error_log("$username login pada " . date('Y-m-d H:i:s'));
});
-// Mendefinisikan rute
+// Menentukan jalur
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Telah login!";
+ echo "Terlogin!";
});
Flight::start();
```
-- **Pro**: Sederhana, tidak ada file tambahan, bagus untuk proyek kecil.
-- **Kontra**: Dapat menjadi berantakan seiring pertumbuhan aplikasi Anda dengan lebih banyak acara dan rute.
+- **Kelebihan**: Sederhana, tidak perlu file tambahan, bagus untuk proyek kecil.
+- **Kekurangan**: Dapat menjadi berantakan seiring pertumbuhan aplikasi Anda dengan lebih banyak acara dan jalur.
-### Opsi 2: File `events.php` Terpisah
-Untuk aplikasi yang sedikit lebih besar, pertimbangkan untuk memindahkan pendaftaran acara ke dalam file khusus seperti `app/config/events.php`. Sertakan file ini di `index.php` Anda sebelum rute Anda. Ini meniru cara rute sering diorganisir dalam `app/config/routes.php` di proyek Flight.
+### Opsi 2: File Terpisah `events.php`
+Untuk aplikasi yang sedikit lebih besar, pertimbangkan untuk memindahkan pendaftaran acara ke dalam file khusus seperti `app/config/events.php`. Sertakan file ini di `index.php` Anda sebelum jalur Anda. Ini menyerupai bagaimana jalur sering diorganisir di `app/config/routes.php` dalam proyek Flight.
```php
// app/config/events.php
@@ -160,16 +160,16 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Telah login!";
+ echo "Terlogin!";
});
Flight::start();
```
-- **Pro**: Menjaga `index.php` terfokus pada routing, mengorganisir acara secara logis, mudah ditemukan dan diedit.
-- **Kontra**: Menambahkan sedikit struktur, yang mungkin terasa berlebihan untuk aplikasi yang sangat kecil.
+- **Kelebihan**: Menjaga `index.php` fokus pada pengalihan, mengorganisir acara secara logis, mudah ditemukan dan diperbarui.
+- **Kekurangan**: Menambah sedikit struktur, yang mungkin terasa berlebihan untuk aplikasi yang sangat kecil.
-### Opsi 3: Dekat Tempat Acara Dipicu
-Pendekatan lain adalah mendaftarkan acara dekat tempat mereka dipicu, seperti di dalam kontroler atau definisi rute. Ini bekerja dengan baik jika sebuah acara khusus untuk satu bagian aplikasi Anda.
+### Opsi 3: Dekat Tempat Mereka Dipicu
+Pendekatan lain adalah mendaftarkan acara dekat tempat mereka dipicu, seperti di dalam pengontrol atau definisi jalur. Ini bekerja dengan baik jika acara spesifik untuk satu bagian dari aplikasi Anda.
```php
Flight::route('/signup', function () {
@@ -180,19 +180,19 @@ Flight::route('/signup', function () {
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Telah mendaftar!";
+ echo "Terdaftar!";
});
```
-- **Pro**: Menjaga kode terkait bersama, baik untuk fitur terisolasi.
-- **Kontra**: Menyebar pendaftaran acara, membuatnya lebih sulit untuk melihat semua acara sekaligus; berisiko pendaftaran duplikat jika tidak hati-hati.
+- **Kelebihan**: Menjaga kode yang terkait bersama, bagus untuk fitur terisolasi.
+- **Kekurangan**: Mendistribusikan pendaftaran acara, membuat lebih sulit untuk melihat semua acara sekaligus; risiko pendaftaran duplikat jika tidak hati-hati.
### Praktik Terbaik untuk Flight
- **Mulailah Sederhana**: Untuk aplikasi kecil, letakkan acara di `index.php`. Ini cepat dan selaras dengan minimalisme Flight.
-- **Bertumbuh dengan Cerdas**: Saat aplikasi Anda berkembang (misalnya, lebih dari 5-10 acara), gunakan file `app/config/events.php`. Ini adalah langkah alami ke atas, seperti mengorganisir rute, dan menjaga kode Anda rapi tanpa menambahkan framework yang kompleks.
-- **Hindari Over-Engineering**: Jangan membuat kelas atau direktori "manajer acara" yang besar kecuali aplikasi Anda sangat besar—Flight berkembang dalam kesederhanaan, jadi jaga tetap ringan.
+- **Berkembang dengan Cerdas**: Seiring pertumbuhan aplikasi Anda (misalnya, lebih dari 5-10 acara), gunakan file `app/config/events.php`. Ini merupakan langkah alami ke atas, seperti mengorganisir jalur, dan menjaga kode Anda rapi tanpa menambah kerumitan.
+- **Hindari Over-Engineering**: Jangan buat kelas atau direktori “manajer acara” yang besar kecuali aplikasi Anda menjadi besar—Flight berkembang pada kesederhanaan, jadi pertahankan agar tetap ringan.
### Tip: Kelompokkan Berdasarkan Tujuan
-Di `events.php`, kelompokkan acara terkait (misalnya, semua acara terkait pengguna bersama) dengan komentar untuk kejelasan:
+Dalam `events.php`, kelompokkan acara terkait (misalnya, semua acara yang terkait dengan pengguna bersama-sama) dengan komentar untuk kejelasan:
```php
// app/config/events.php
@@ -214,7 +214,7 @@ Struktur ini berkembang dengan baik dan tetap ramah pemula.
## Contoh untuk Pemula
-Mari kita lihat beberapa skenario dunia nyata untuk menunjukkan bagaimana acara bekerja dan mengapa mereka berguna.
+Mari kita tinjau beberapa skenario dunia nyata untuk menunjukkan bagaimana acara bekerja dan mengapa mereka berguna.
### Contoh 1: Mencatat Login Pengguna
```php
@@ -224,24 +224,24 @@ Flight::onEvent('user.login', function ($username) {
error_log("$username login pada $time");
});
-// Langkah 2: Memicu di aplikasi Anda
+// Langkah 2: Memicunya di aplikasi Anda
Flight::route('/login', function () {
- $username = 'bob'; // Asumsikan ini berasal dari formulir
+ $username = 'bob'; // Anggap ini berasal dari formulir
Flight::triggerEvent('user.login', $username);
echo "Hai, $username!";
});
```
-**Mengapa Ini Berguna**: Kode login tidak perlu tahu tentang pencatatan—hanya memicu acara. Anda bisa menambahkan lebih banyak pendengar (misalnya, mengirim email selamat datang) tanpa mengubah rute.
+**Mengapa Ini Berguna**: Kode login tidak perlu tahu tentang pencatatan—ia hanya memicu acara. Anda dapat menambahkan lebih banyak pendengar kemudian (misalnya, mengirim email sambutan) tanpa mengubah jalur.
-### Contoh 2: Memberi Tahu tentang Pengguna Baru
+### Contoh 2: Memberitahukan Tentang Pengguna Baru
```php
// Pendengar untuk pendaftaran baru
Flight::onEvent('user.registered', function ($email, $name) {
- // Mensimulasikan mengirim email
+ // Simulasikan pengiriman email
echo "Email dikirim ke $email: Selamat datang, $name!";
});
-// Memicu ketika seseorang mendaftar
+// Memicunya ketika seseorang mendaftar
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
@@ -249,41 +249,47 @@ Flight::route('/signup', function () {
echo "Terima kasih telah mendaftar!";
});
```
-**Mengapa Ini Berguna**: Logika pendaftaran fokus pada pembuatan pengguna, sementara acara menangani notifikasi. Anda dapat menambahkan lebih banyak pendengar (misalnya, mencatat pendaftaran) nanti.
+**Mengapa Ini Berguna**: Logika pendaftaran fokus pada pembuatan pengguna, sementara acara menangani notifikasi. Anda dapat menambahkan lebih banyak pendengar (misalnya, mencatat pendaftaran) kemudian.
### Contoh 3: Menghapus Cache
```php
// Pendengar untuk menghapus cache
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Menghapus cache sesi jika berlaku
+ unset($_SESSION['pages'][$pageId]); // Hapus cache sesi jika berlaku
echo "Cache dihapus untuk halaman $pageId.";
});
-// Memicu saat halaman diedit
+// Memicunya ketika sebuah halaman diedit
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Asumsikan kami memperbarui halaman
+ // Anggap kami telah memperbarui halaman
Flight::triggerEvent('page.updated', $pageId);
echo "Halaman $pageId diperbarui.";
});
```
-**Mengapa Ini Berguna**: Kode pengeditan tidak peduli tentang caching—hanya memberi sinyal pembaruan. Bagian lain dari aplikasi dapat bereaksi sesuai kebutuhan.
+**Mengapa Ini Berguna**: Kode pengeditan tidak peduli tentang caching—ia hanya memberi sinyal pembaruan. Bagian lain aplikasi dapat merespons sesuai kebutuhan.
## Praktik Terbaik
-- **Berikan Nama Acara dengan Jelas**: Gunakan nama spesifik seperti `'user.login'` atau `'page.updated'` agar jelas apa fungsinya.
-- **Simpan Pendengar Sederhana**: Jangan letakkan tugas lambat atau kompleks dalam pendengar—jaga aplikasi Anda cepat.
-- **Uji Acara Anda**: Picu secara manual untuk memastikan pendengar berfungsi seperti yang diharapkan.
-- **Gunakan Acara dengan Bijak**: Mereka hebat untuk pemisahan, tetapi terlalu banyak bisa membuat kode Anda sulit diikuti—gunakan ketika masuk akal.
+- **Berikan Nama Acara dengan Jelas**: Gunakan nama spesifik seperti `'user.login'` atau `'page.updated'` sehingga jelas apa yang mereka lakukan.
+- **Jaga Pendengar Tetap Sederhana**: Jangan letakkan tugas yang lambat atau rumit dalam pendengar—jaga aplikasi Anda tetap cepat.
+- **Uji Acara Anda**: Picu mereka secara manual untuk memastikan pendengar bekerja seperti yang diharapkan.
+- **Gunakan Acara dengan Bijak**: Mereka sangat berguna untuk pemisahan, tetapi terlalu banyak dapat membuat kode Anda sulit diikuti—gunakan mereka ketika masuk akal.
-Sistem acara di Flight PHP, dengan `Flight::onEvent()` dan `Flight::triggerEvent()`, memberi Anda cara yang sederhana namun kuat untuk membangun aplikasi yang fleksibel. Dengan membiarkan bagian-bagian berbeda dari aplikasi Anda berkomunikasi melalui acara, Anda dapat menjaga kode Anda terorganisir, dapat digunakan kembali, dan mudah untuk diperluas. Apakah Anda sedang mencatat tindakan, mengirim notifikasi, atau mengelola pembaruan, acara membantu Anda melakukannya tanpa merumitkan logika Anda. Ditambah dengan kemampuan untuk menimpa metode-metode ini, Anda memiliki kebebasan untuk menyesuaikan sistem dengan kebutuhan Anda. Mulailah kecil dengan satu acara, dan saksikan bagaimana hal itu mengubah struktur aplikasi Anda!
+Sistem acara di Flight PHP, dengan `Flight::onEvent()` dan `Flight::triggerEvent()`, memberi Anda cara sederhana dan kuat untuk membangun aplikasi yang fleksibel. Dengan membiarkan berbagai bagian dari aplikasi Anda berkomunikasi satu sama lain melalui acara, Anda dapat menjaga kode Anda terorganisir, dapat digunakan kembali, dan mudah untuk diperluas. Apakah Anda mencatat tindakan, mengirim notifikasi, atau mengelola pembaruan, acara membantu Anda melakukannya tanpa mempersulit logika Anda. Selain itu, dengan kemampuan untuk mengganti metode ini, Anda memiliki kebebasan untuk menyesuaikan sistem sesuai kebutuhan Anda. Mulailah dengan satu acara kecil, dan saksikan bagaimana hal itu mengubah struktur aplikasi Anda!
## Acara Bawaan
-Flight PHP dilengkapi dengan beberapa acara bawaan yang dapat Anda gunakan untuk terhubung ke siklus hidup framework. Acara ini dipicu pada titik tertentu dalam siklus permintaan/respons, memungkinkan Anda untuk mengeksekusi logika kustom saat tindakan tertentu terjadi.
+Flight PHP dilengkapi dengan beberapa acara bawaan yang dapat Anda gunakan untuk menyambungkan siklus hidup framework. Acara-acara ini dipicu pada poin tertentu dalam siklus permintaan/respons, memungkinkan Anda untuk mengeksekusi logika kustom ketika tindakan tertentu terjadi.
### Daftar Acara Bawaan
-- `flight.request.received`: Dipicu saat permintaan diterima, diparsing, dan diproses.
-- `flight.route.middleware.before`: Dipicu setelah middleware sebelum dieksekusi.
-- `flight.route.middleware.after`: Dipicu setelah middleware setelah dieksekusi.
-- `flight.route.executed`: Dipicu setelah sebuah rute dieksekusi dan diproses.
-- `flight.response.sent`: Dipicu setelah respons dikirim ke klien.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` Dipicu ketika permintaan diterima, diparsing dan diproses.
+- **flight.error**: `function(Throwable $exception)` Dipicu ketika kesalahan terjadi selama siklus permintaan.
+- **flight.redirect**: `function(string $url, int $status_code)` Dipicu ketika pengalihan diinisiasi.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Dipicu ketika cache diperiksa untuk kunci tertentu dan apakah cache tersebut hit atau miss.
+- **flight.middleware.before**: `function(Route $route)` Dipicu setelah middleware sebelum dieksekusi.
+- **flight.middleware.after**: `function(Route $route)` Dipicu setelah middleware setelah dieksekusi.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Dipicu setelah middleware dieksekusi.
+- **flight.route.matched**: `function(Route $route)` Dipicu ketika sebuah rute dicocokkan, tetapi belum dieksekusi.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Dipicu setelah rute dieksekusi dan diproses. `$executionTime` adalah waktu yang dibutuhkan untuk mengeksekusi rute (memanggil pengontrol, dll).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Dipicu setelah tampilan dirender. `$executionTime` adalah waktu yang dibutuhkan untuk merender template. **Catatan: Jika Anda mengganti metode `render`, Anda perlu memicu ulang acara ini.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Dipicu setelah respons dikirim ke klien. `$executionTime` adalah waktu yang dibutuhkan untuk membangun respons.
\ No newline at end of file
diff --git a/content/v3/ja/awesome-plugins/apm.md b/content/v3/ja/awesome-plugins/apm.md
new file mode 100644
index 0000000..83e81e1
--- /dev/null
+++ b/content/v3/ja/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM ドキュメント
+
+FlightPHP APM へようこそ—あなたのアプリのパーソナルパフォーマンスコーチ!このガイドは、FlightPHP でのアプリケーションパフォーマンスモニタリング (APM) の設定、使用、および習得のためのロードマップです。遅いリクエストを追いかけたい場合でも、単にレイテンシチャートに夢中になりたい場合でも、ご安心ください。あなたのアプリを速くし、ユーザーを幸せにし、デバッグセッションを簡単にしましょう!
+
+## なぜ APM が重要か
+
+これを想像してみてください:あなたのアプリは忙しいレストランです。注文がどれくらい時間がかかるか、キッチンがどこで詰まっているかを追跡する方法がなければ、顧客がイライラしている理由を推測することになります。APM はあなたの副料理長です—受信リクエストからデータベースクエリまで、すべてのステップを監視し、あなたを遅くしているものをフラグ付けします。遅いページはユーザーを失います(調査によれば、サイトの読み込みに 3 秒以上かかると 53% のユーザーが離脱します!)、そして APM はそれらの問題を痛む前にキャッチします。この仕組みは、あらかじめ安心感をもたらします—「なぜこれが壊れているのか?」という瞬間を減らし、「これがどれだけスムーズに動くか!」という勝利を増やします。
+
+## インストール
+
+Composer で始めましょう:
+
+```bash
+composer require flightphp/apm
+```
+
+必要なもの:
+- **PHP 7.4+**: 最新の PHP をサポートしつつ、LTS Linux ディストリビューションとの互換性を保ちます。
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: 軽量フレームワークです。
+
+## 始め方
+
+APM の素晴らしさへのステップバイステップはこちら:
+
+### 1. APM を登録する
+
+これを `index.php` または `services.php` に入れてトラッキングを開始します:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**ここで何が起こっているのですか?**
+- `LoggerFactory::create()` はあなたの設定を取得し(それについては後で詳しく)、ロガーを設定します—デフォルトは SQLite です。
+- `Apm` は主役で、Flight のイベント(リクエスト、ルート、エラーなど)をリッスンし、メトリクスを収集します。
+- `bindEventsToFlightInstance($app)` はそれをあなたの Flight アプリに結び付けます。
+
+**プロのヒント:サンプリング**
+アプリが忙しい場合、*すべての*リクエストをロギングすることは負荷をかけるかもしれません。サンプルレート(0.0 から 1.0)を使用します:
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // 10% のリクエストをログ
+```
+
+これにより、パフォーマンスをスナッピーに保ちながら、しっかりとしたデータを得ることができます。
+
+### 2. 設定を行う
+
+これを実行して `.runway-config.json` を作成します:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**これは何をしますか?**
+- 生のメトリクスがどこから来るか(ソース)と、処理されたデータがどこに行くか(宛先)を尋ねるウィザードが起動します。
+- デフォルトは SQLite です—例えば、ソースには `sqlite:/tmp/apm_metrics.sqlite`、宛先には別のものを使用します。
+- 結果、次のような設定が生成されます:
+ ```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"
+ }
+ }
+ ```
+
+**なぜ 2 つの場所?**
+生のメトリクスはすぐに蓄積されます(フィルタリングされていないログを考えてください)。ワーカーはそれらをダッシュボードのための構造化された宛先に処理します。すっきりと保つためです!
+
+### 3. ワーカーでメトリクスを処理する
+
+ワーカーは生のメトリクスをダッシュボード用のデータに変換します。これを一度実行します:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**これは何をしていますか?**
+- あなたのソース(例: `apm_metrics.sqlite`)から読み取ります。
+- あなたの宛先に最大 100 メトリクス(デフォルトのバッチサイズ)を処理します。
+- 処理が完了するか、メトリクスが残っていない場合に停止します。
+
+**常に実行する**
+ライブアプリの場合、継続的な処理が望ましいです。こちらがあなたの選択肢です:
+
+- **デーモンモード**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ 常に実行し、到着するメトリクスを処理します。開発や小規模セットアップに最適です。
+
+- **クロンタブ**:
+ あなたのクロンタブにこれを追加します(`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` で再接続
+ ```
+ ログアウトしても実行され続けます。
+
+- **カスタム調整**:
+ ```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 分後に終了します。
+
+**なぜ気にする必要がありますか?**
+ワーカーがなければ、あなたのダッシュボードは空っぽです。生のログとアクション可能なインサイトの橋渡しです。
+
+### 4. ダッシュボードを起動する
+
+アプリの重要データを確認します:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**これは何ですか?**
+- `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`: PHP が PATH にない場合は指し示してください。
+
+ブラウザで 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` に設定します。
+
+#### 別のダッシュボードが必要ですか?
+
+ご自身のダッシュボードを構築したい場合は、vendor/flightphp/apm/src/apm/presenter ディレクトリを参照して、自分のダッシュボードのデータを提示する方法のアイデアを得てください!
+
+## ダッシュボードの特徴
+
+ダッシュボードはあなたの APM HQ です—ここで見ることができます:
+
+- **リクエストログ**: タイムスタンプ、URL、レスポンスコード、合計時間とともにすべてのリクエスト。クリックして「詳細」を表示すれば、ミドルウェア、クエリ、エラーを確認できます。
+- **最も遅いリクエスト**: 時間を浪費しているトップ 5 のリクエスト(例: “/api/heavy” で 2.5s)。
+- **最も遅いルート**: 平均時間別のトップ 5 ルート—パターンを見つけるのに便利です。
+- **エラーレート**: 失敗しているリクエストの割合(例: 2.3% の 500s)。
+- **レイテンシパーセンタイル**: 95 番目(p95)および 99 番目(p99)レスポンスタイム—最悪のシナリオを把握しましょう。
+- **レスポンスコードチャート**: 時間の経過に伴う 200s、404s、500s を視覚化します。
+- **長いクエリ/ミドルウェア**: 最も遅いデータベース呼び出しとミドルウェアレイヤーのトップ 5。
+- **キャッシュヒット/ミス**: キャッシュがどれだけ良い仕事をしているか。
+
+**追加情報**:
+- 「最終時間」、「最終日」または「最終週」でフィルタリングします。
+- 夜更かしセッション用にダークモードを切り替えます。
+
+**例**:
+`/users` へのリクエストは次のように表示されるかもしれません:
+- 合計時間:150ms
+- ミドルウェア: `AuthMiddleware->handle`(50ms)
+- クエリ: `SELECT * FROM users`(80ms)
+- キャッシュ: `user_list` でヒット(5ms)
+
+## カスタムイベントの追加
+
+API 呼び出しや支払いプロセスのように、何でもトラッキングします:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**どこで表示されますか?**
+ダッシュボードのリクエスト詳細の「カスタムイベント」に表示されます—きれいな JSON 形式で展開可能です。
+
+**使用例**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+これで、その API があなたのアプリを引きずり下ろしているかどうかを見ることができます!
+
+## データベースモニタリング
+
+PDO クエリを次のようにトラッキングします:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**得られるもの**:
+- クエリテキスト(例: `SELECT * FROM users WHERE id = ?`)
+- 実行時間(例: 0.015s)
+- 行数(例: 42)
+
+**ご注意**:
+- **オプション**: 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`: 非停止で実行—ライブモニタリングに最適です。
+
+**例**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+1 時間実行し、1 回に 100 メトリクスを処理します。
+
+## トラブルシューティング
+
+詰まったら?以下を試してください:
+
+- **ダッシュボードデータがない場合は?**
+ - ワーカーは実行中ですか? `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 ログをチェックします。
+
+- **ダッシュボードが起動しない場合は?**
+ - ポート 8001 が使用中ですか? `--port 8080` を使用します。
+ - PHP が見つかりませんか? `--php-path /usr/bin/php` を使用します。
+ - ファイアウォールがブロックしていますか? ポートを開放するか、`--host localhost` を使用します。
+
+- **遅すぎる?**
+ - サンプリングレートを下げます: `$Apm = new Apm($ApmLogger, 0.05)`(5%)。
+ - バッチサイズを減少させます: `--batch_size 20`。
\ 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 9888708..0cfe3de 100644
--- a/content/v3/ja/awesome-plugins/awesome_plugins.md
+++ b/content/v3/ja/awesome-plugins/awesome_plugins.md
@@ -1,78 +1,83 @@
# 素晴らしいプラグイン
-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) - FlightPHPを使用してAPIファーストアプローチでAPIを構築する方法についてDaniel Schreiberが書いたブログ投稿。
-- [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) - FlightPHPを使ってAPIファーストアプローチでAPIを構築する方法について、Daniel Schreiberが執筆したブログ記事です。
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UIは、FlightプロジェクトのAPIドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これはSwaggerドキュメントを生成するためのPHPライブラリです。
+
+## アプリケーションパフォーマンスモニタリング (APM)
+
+アプリケーションパフォーマンスモニタリング(APM)は、すべてのアプリケーションにとって重要です。アプリケーションがどのように機能しているか、ボトルネックがどこにあるかを理解するのに役立ちます。Flightで使用できるAPMツールがいくつかあります。
+- ベータ[flightphp/apm](/awesome-plugins/apm) - Flight APMは、Flightアプリケーションを監視するために使用できるシンプルなAPMライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。
## 認証/認可
-認証と認可は、誰が何にアクセスできるかを管理するために必要なアプリケーションにとって重要です。
+認証と認可は、誰が何にアクセスできるかのコントロールが必要なすべてのアプリケーションにとって重要です。
-- official [flightphp/permissions](/awesome-plugins/permissions) - 公式Flight権限ライブラリ。このライブラリは、アプリケーションにユーザーとアプリケーションレベルの権限を追加するための簡単な方法です。
+- 公式 [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は、Flightアプリケーションを管理するのに役立つCLIアプリケーションです。
+- 公式 [flightphp/runway](/awesome-plugins/runway) - Runwayは、あなたのFlightアプリケーションを管理するのに役立つCLIアプリケーションです。
## クッキー
-クッキーはクライアント側に小さなデータを保存するための優れた方法です。ユーザーの設定やアプリケーションの設定などを保存するために使用できます。
+クッキーは、クライアント側に小さなデータを保存する素晴らしい方法です。ユーザーの設定やアプリケーションの設定などを保存するために使用できます。
- [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と一緒に使用できる特徴のあるエラーハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、独自のパネルを追加することも非常に簡単です。
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy)エラーハンドラーと一緒に使用されるこのプラグインは、Flightプロジェクトのデバッグのためのいくつかの追加パネルを追加します。
## データベース
-データベースはほとんどのアプリケーションの中心です。これはデータを保存し、取得する方法です。いくつかのデータベースライブラリは、クエリを書くためのラッパーに過ぎないものもあれば、完全なORMであるものもあります。
+データベースはほとんどのアプリケーションの核心です。データを保存し、取得するための方法です。いくつかのデータベースライブラリは、単にクエリを記述するためのラッパーであり、いくつかは完全なORMです。
-- official [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - コアの一部である公式Flight PDOラッパー。これは、クエリを書いて実行するプロセスを簡素化するためのシンプルなラッパーです。ORMではありません。
-- official [flightphp/active-record](/awesome-plugins/active-record) - 公式Flight ActiveRecord ORM/マッパー。データベース内のデータを簡単に取得して保存するための素晴らしい小さなライブラリです。
+- 公式 [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - コアの一部である公式Flight PDOラッパー。クエリを記述し、実行するプロセスを簡素化するためのシンプルなラッパーです。これはORMではありません。
+- 公式 [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://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.)。最も重要なことは、暗号化キーを公開ディレクトリに保存したり、コードリポジトリにコミットしたりしないことです。
-- [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にはあまり役立ちませんが、ウェブアプリケーションを構築する際には、状態やログイン情報を維持するために重要です。
-- official [flightphp/session](/awesome-plugins/session) - 公式Flightセッションライブラリ。これはセッションデータを保存および取得するために使用できるシンプルなセッションライブラリです。PHPの組み込みのセッションハンドリングを使用しています。
-- [Ghostff/Session](/awesome-plugins/ghost-session) - PHPセッションマネージャー(非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化にPHP open_sslを使用します。
+- 公式 [flightphp/session](/awesome-plugins/session) - 公式Flightセッションライブラリ。セッションデータを保存および取得するために使用できるシンプルなセッションライブラリです。PHPの組み込みセッション処理を使用しています。
+- [Ghostff/Session](/awesome-plugins/ghost-session) - PHPセッションマネージャー(ノンブロッキング、フラッシュ、セグメント、セッション暗号化)。オプションでセッションデータの暗号化/復号化用にPHP open_sslを使用します。
## テンプレーティング
-テンプレーティングは、UIを持つWebアプリケーションの中心です。Flightと一緒に使用できるテンプレーティングエンジンがいくつかあります。
+テンプレーティングは、UIを持つウェブアプリケーションの中心です。Flightと共に使用できるテンプレーティングエンジンがいくつかあります。
-- deprecated [flightphp/core View](/learn#views) - これはコアの一部である非常に基本的なテンプレーティングエンジンです。プロジェクトにページが数ページ以上ある場合は使用することをお勧めしません。
-- [latte/latte](/awesome-plugins/latte) - Latteは、非常に使いやすく、TwigやSmartyよりもPHPの構文に近い完全な機能を持つテンプレーティングエンジンです。また、拡張や独自のフィルターや関数の追加も非常に簡単です。
+- 非推奨 [flightphp/core View](/learn#views) - これはコアの一部である非常に基本的なテンプレーティングエンジンです。プロジェクトに数ページ以上がある場合の使用は推奨されません。
+- [latte/latte](/awesome-plugins/latte) - Latteは、非常に使いやすく、TwigやSmartyよりもPHP構文に近いフル機能のテンプレーティングエンジンです。また、自分のフィルターや関数を追加することも非常に簡単です。
## 貢献
diff --git a/content/v3/ja/awesome-plugins/tracy_extensions.md b/content/v3/ja/awesome-plugins/tracy_extensions.md
index c5d60a2..0f5ddf4 100644
--- a/content/v3/ja/awesome-plugins/tracy_extensions.md
+++ b/content/v3/ja/awesome-plugins/tracy_extensions.md
@@ -1,32 +1,32 @@
-Tracy Flight Panel Extensions
+Tracy Flight パネル拡張
=====
-これはFlightを使いやすくするための拡張機能セットです。
+これは、Flightをよりリッチに使用するための一連の拡張です。
- Flight - すべてのFlight変数を分析します。
-- Database - ページで実行されたすべてのクエリを分析します(データベース接続を正しく初期化した場合)
-- Request - `$_SERVER`変数を分析し、すべてのグローバルペイロード(`$_GET`、`$_POST`、`$_FILES`)を調べます。
-- Session - セッションがアクティブな場合、すべての`$_SESSION`変数を分析します。
+- Database - ページで実行されたすべてのクエリを分析します(データベース接続を正しく開始した場合)。
+- Request - すべての `$_SERVER` 変数を分析し、すべてのグローバルペイロード(`$_GET`、`$_POST`、`$_FILES`)を調べます。
+- Session - セッションがアクティブな場合、すべての `$_SESSION` 変数を分析します。
-これはパネルです
+これがパネルです。

-それぞれのパネルはアプリケーションについて非常に役立つ情報を表示します!
+それぞれのパネルは、アプリケーションに関する非常に役立つ情報を表示します!



-[ここをクリック](https://github.com/flightphp/tracy-extensions)してコードを表示します。
+コードは[こちら](https://github.com/flightphp/tracy-extensions)から確認できます。
インストール
-------
-`composer require flightphp/tracy-extensions --dev` を実行して、準備が整います!
+`composer require flightphp/tracy-extensions --dev`を実行すると、準備完了です!
設定
-------
-これを開始するために行う必要がある設定は非常に少ないです。これを使用する前に Tracy デバッガを初期化する必要があります [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+これを始めるために必要な設定はほとんどありません。使用する前にTracyデバッガを初期化する必要があります。[https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // これは false にする必要があります、さもないとTracy が実際にレンダリングできません :(
+ // これはfalseである必要があります。でないとTracyは実際にレンダリングできません :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
-// ルートやその他のもの...
+// ルートやその他のこと...
Flight::start();
```
### Latte
-プロジェクトにLatteがインストールされている場合、
-テンプレートを分析するためのLatteパネルを使用できます。
-`TracyExtensionLoader` コンストラクターの第二パラメーターで `latte` キーでLatteインスタンスを渡すことができます。
+プロジェクトにLatteがインストールされている場合、Latteパネルを使用してテンプレートを分析できます。 `TracyExtensionLoader`コンストラクタの二番目のパラメータに`latte`キーを使用してLatteインスタンスを渡すことができます。
```php
@@ -105,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // これでLatte PanelをTracyに追加します
+ // ここでLatteパネルをTracyに追加します
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // これは false にする必要があります、さもないとTracy が実際にレンダリングできません :(
+ // これはfalseである必要があります。でないとTracyは実際にレンダリングできません :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
-}
\ No newline at end of file
+}
+```
\ No newline at end of file
diff --git a/content/v3/ja/learn/events.md b/content/v3/ja/learn/events.md
index edc7225..697887a 100644
--- a/content/v3/ja/learn/events.md
+++ b/content/v3/ja/learn/events.md
@@ -1,25 +1,25 @@
# Flight PHPにおけるイベントシステム (v3.15.0+)
-Flight PHPは、アプリケーション内でカスタムイベントを登録およびトリガーできる軽量で直感的なイベントシステムを導入します。 `Flight::onEvent()` および `Flight::triggerEvent()` の追加により、アプリのライフサイクルの重要な瞬間にフックしたり、自分のイベントを定義したりして、コードをよりモジュール化および拡張可能にすることができます。これらのメソッドはFlightの**マッパブルメソッド**の一部であり、必要に応じてその動作をオーバーライドできます。
+Flight PHPは、アプリケーション内でカスタムイベントを登録およびトリガーできる軽量かつ直感的なイベントシステムを導入します。`Flight::onEvent()`と`Flight::triggerEvent()`を追加することで、アプリのライフサイクルの重要な瞬間にフックしたり、独自のイベントを定義したりして、コードをよりモジュール化し拡張可能にすることができます。これらのメソッドはFlightの**マッピング可能メソッド**の一部であり、ニーズに合わせてその動作をオーバーライドすることが可能です。
-このガイドでは、イベントの価値、使用方法、および初心者がその力を理解するのに役立つ実践的な例を含め、イベントの使用を開始するために必要なすべての情報をカバーします。
+このガイドでは、イベントの価値、使い方、および初心者がそのパワーを理解するのを助ける実用的な例を含め、イベントを始めるために必要なすべてのことを説明します。
## なぜイベントを使用するのか?
-イベントは、アプリケーションの異なる部分を分離して、それぞれが過度に依存しないようにします。この分離は、しばしば**デカップリング**と呼ばれ、コードの更新、拡張、デバッグを容易にします。すべてを大きな塊で書く代わりに、特定のアクション(イベント)に応答する小さく独立したロジックに分割できます。
+イベントを使用することで、アプリケーションの異なる部分を分離し、互いに過度に依存しないようにすることができます。この分離はしばしば**デカップリング**と呼ばれ、コードの更新、拡張、デバッグが容易になります。すべてを一つの大きな塊で書く代わりに、特定のアクション(イベント)に応じて反応する小さく独立した部分にロジックを分割できます。
-ブログアプリを構築していると想像してください:
-- ユーザーがコメントを投稿したとき、次のことを行いたいかもしれません:
+ブログアプリを構築していると仮定しましょう:
+- ユーザーがコメントを投稿したとき、あなたは以下を行いたいかもしれません:
- コメントをデータベースに保存する。
- - ブログの所有者にメールを送信する。
- - セキュリティのためにアクションを記録する。
+ - ブログのオーナーにメールを送信する。
+ - セキュリティのためにアクションをログに記録する。
-イベントがないと、すべてを1つの関数に無理やり詰め込むことになります。イベントを使用すると、コメントを保存する部分、`'comment.posted'`のようなイベントをトリガーする部分、そしてメールやログを処理するリスナーを別々に設けることができます。これにより、コードがすっきりし、コアのロジックに触れずに機能(通知など)を追加または削除できます。
+イベントがなければ、すべてを一つの関数に詰め込むことになります。イベントを使用すると、これを分割できます:ある部分がコメントを保存し、別の部分が`'comment.posted'`のようなイベントをトリガーし、別のリスナーがメールとロギングを処理します。これにより、コードがクリーンになり、コアロジックに手を触れずに機能(通知など)を追加または削除することができます。
### 一般的な使用例
-- **ロギング**:ログインやエラーのようなアクションを記録し、メインのコードを混乱させずに済みます。
+- **ロギング**:ログインやエラーのようなアクションを主要なコードを混雑させずに記録できます。
- **通知**:何かが発生したときにメールやアラートを送信します。
-- **更新**:キャッシュを更新したり、他のシステムに変更を通知したりします。
+- **更新**:キャッシュをリフレッシュしたり、他のシステムに変更を通知します。
## イベントリスナーの登録
@@ -30,103 +30,103 @@ Flight PHPは、アプリケーション内でカスタムイベントを登録
Flight::onEvent(string $event, callable $callback): void
```
- `$event`:イベントの名前(例:`'user.login'`)。
-- `$callback`:イベントがトリガーされたときに実行する関数。
+- `$callback`:イベントがトリガーされたときに実行される関数。
### 仕組み
-あなたは、イベントが発生したときにFlightに何をするかを知らせることで、「サブスクライブ」します。コールバックは、イベントトリガーから渡される引数を受け取ることができます。
+あなたは、イベントが発生したときにFlightに何をするかを伝えることによって、イベントに「登録」します。コールバックは、イベントトリガーから渡された引数を受け取ることができます。
-Flightのイベントシステムは同期的であり、これは各イベントリスナーが順次実行され、1つずつ処理されることを意味します。イベントをトリガーすると、そのイベントのすべての登録されたリスナーが実行を完了するまで、あなたのコードは続行しません。これは非同期イベントシステムとは異なり、リスナーが並行して動作したり、後で実行される可能性があるため、理解することが重要です。
+Flightのイベントシステムは同期的であり、これは各イベントリスナーが順番に、1つずつ実行されることを意味します。イベントをトリガーすると、そのイベントに登録されたすべてのリスナーが実行を完了し、その後にコードが続行されます。これは、リスナーが並行して実行されるか後で実行される非同期イベントシステムとは異なるため、理解することが重要です。
-### 簡単な例
+### シンプルな例
```php
Flight::onEvent('user.login', function ($username) {
- echo "お帰りなさい、$username!";
+ echo "おかえりなさい、$username!";
});
```
-ここでは、`'user.login'`イベントがトリガーされると、ユーザーの名前で挨拶します。
+ここで、`'user.login'`イベントがトリガーされると、ユーザーの名前で挨拶されます。
### 重要なポイント
-- 同じイベントに複数のリスナーを追加できます。リスナーは登録した順番で実行されます。
-- コールバックは関数、無名関数、またはクラスのメソッドである可能性があります。
+- 同じイベントに複数のリスナーを追加できます—登録した順序で実行されます。
+- コールバックは関数、匿名関数、またはクラスのメソッドであることができます。
-## イベントをトリガーする
+## イベントのトリガー
-イベントを発生させるには、`Flight::triggerEvent()`を使用します。これにより、Flightはそのイベントのために登録されたすべてのリスナーを実行し、提供されたデータを渡します。
+イベントを発生させるには、`Flight::triggerEvent()`を使用します。これにより、Flightはそのイベントに登録されたすべてのリスナーを実行し、提供したデータを渡します。
### 構文
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`:トリガーしているイベントの名前(登録されたイベントと一致する必要があります)。
-- `...$args`:リスナーに送信するオプションの引数(任意の数の引数が可能です)。
+- `$event`:トリガーするイベントの名前(登録されたイベントと一致する必要があります)。
+- `...$args`:リスナーに送信するオプションの引数(任意の数の引数を送信できます)。
-### 簡単な例
+### シンプルな例
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-これは、`'user.login'`イベントをトリガーし、先に定義したリスナーに`'alice'`を送信します。その結果、`お帰りなさい、alice!`と出力されます。
+これは`'user.login'`イベントをトリガーし、以前に定義したリスナーに`'alice'`を送信します。出力は次のようになります:`おかえりなさい、alice!`。
### 重要なポイント
-- リスナーが登録されていない場合、何も起こりません—アプリは壊れません。
-- スプレッドオペレーター(`...`)を使用して、柔軟に複数の引数を渡します。
+- 登録されたリスナーがない場合、何も起こりません—アプリが壊れることはありません。
+- スプレッド演算子(`...`)を使用して、柔軟に複数の引数を渡します。
### イベントリスナーの登録
...
-**さらなるリスナーの停止**:
-リスナーが `false` を返すと、そのイベントの追加のリスナーは実行されません。これは、特定の条件に基づいてイベントチェーンを停止することを可能にします。リスナーの順序は重要です。最初に`false`を返すリスナーが、他のリスナーの実行を停止します。
+**さらなるリスナーを停止する**:
+リスナーが`false`を返すと、そのイベントの追加のリスナーは実行されません。これにより、特定の条件に基づいてイベントチェーンを停止できます。リスナーの順序は重要であり、最初に`false`を返すものが残りの実行を停止します。
**例**:
```php
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // 続くリスナーを停止
+ return false; // 後続のリスナーを停止
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // これは送信されない
+ sendWelcomeEmail($username); // これは決して送信されません
});
```
## イベントメソッドのオーバーライド
-`Flight::onEvent()`および`Flight::triggerEvent()`は[拡張可能](/learn/extending)であり、それらの動作を再定義できます。これは、イベントシステムをカスタマイズしたい上級ユーザーにとって非常に便利です。たとえば、ロギングを追加したり、イベントのディスパッチ方法を変更したりできます。
+`Flight::onEvent()`と`Flight::triggerEvent()`は[拡張可能](/learn/extending)であり、機能を再定義することができます。これは、ログ記録を追加したり、イベントがどのように派遣されるかを変更したりしたい高度なユーザーにとって素晴らしいものです。
### 例:`onEvent`のカスタマイズ
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // すべてのイベント登録をログに記録
+ // 新しいイベントリスナーの追加をログに記録
error_log("新しいイベントリスナーが追加されました: $event");
- // デフォルトの動作を呼び出します(内部イベントシステムを仮定)
+ // デフォルトの動作を呼び出す(内部イベントシステムを想定)
Flight::_onEvent($event, $callback);
});
```
-これで、イベントを登録するたびに、それをログに記録してから続行します。
+これにより、イベントを登録するたびに、処理を続ける前にログが記録されます。
### なぜオーバーライドするのか?
-- デバッグやモニタリングを追加するため。
-- 特定の環境でイベントを制限するため(例:テスト中に無効にする)。
-- 別のイベントライブラリと統合するため。
+- デバッグやモニタリングを追加。
+- 特定の環境(例:テスト中に無効化)でイベントを制限。
+- 別のイベントライブラリと統合。
-## イベントをどこに置くべきか
+## イベントを配置する場所
-初心者として、*アプリにこれらすべてのイベントをどこに登録すればよいのか?* Flightのシンプルさは厳格なルールがないことを意味します。プロジェクトにとって合理的な場所に配置できます。しかし、整理された状態を保つことで、アプリが成長するときにコードを維持しやすくなります。以下は、Flightの軽量な特性に合わせた実践的なオプションとベストプラクティスです。
+初心者として、あなたは疑問に思うかもしれません:*アプリ内のすべてのイベントをどこに登録しますか?* Flightのシンプルさは厳格なルールがないことを意味します—プロジェクトに合った任意の場所に配置できます。ただし、整理された状態を保つことで、アプリが成長したときにコードの維持が楽になります。ここでは、Flightの軽量な性質に合わせた実用的なオプションとベストプラクティスをいくつか示します。
-### オプション 1: メインの`index.php`に
-小さなアプリやクイックプロトタイプでは、ルートと同じく`index.php`ファイル内でイベントを登録できます。これは、シンプルさを重視する場合には良い方法です。
+### オプション1: メインの`index.php`に
+小規模なアプリや迅速なプロトタイプの場合、`index.php`ファイル内にルートと一緒にイベントを登録できます。これにより、すべてが一つの場所にまとまり、シンプルさが優先される場合には良い選択です。
```php
require 'vendor/autoload.php';
-// イベントを登録
+// イベントの登録
Flight::onEvent('user.login', function ($username) {
- error_log("$username が " . date('Y-m-d H:i:s') . " にログインしました");
+ error_log("$usernameは" . date('Y-m-d H:i:s') . "にログインしました");
});
-// ルートを定義
+// ルートの定義
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
@@ -135,20 +135,20 @@ Flight::route('/login', function () {
Flight::start();
```
-- **長所**:シンプルで追加ファイルなし、小さなプロジェクトに最適。
-- **短所**:イベントとルートが増えると混沌とする可能性。
+- **利点**:シンプルで追加のファイルが不要、小規模プロジェクトに最適。
+- **欠点**:アプリが成長すると、より多くのイベントやルートで混雑する可能性がある。
-### オプション 2: 別の`events.php`ファイル
-少し大きなアプリでは、`app/config/events.php`のような専用ファイルにイベント登録を移動することを検討してください。このファイルを`index.php`内のルートの前に含めます。これは、Flightプロジェクトでのルートが`app/config/routes.php`に整理されているのと類似しています。
+### オプション2: 別の`events.php`ファイル
+やや大きなアプリの場合、イベントの登録を`app/config/events.php`のような専用ファイルに移動することを検討してください。このファイルを`index.php`でルートの前にインクルードします。これは、Flightプロジェクトでルートが`app/config/routes.php`に整理されるのと同様です。
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username が " . date('Y-m-d H:i:s') . " にログインしました");
+ error_log("$usernameは" . date('Y-m-d H:i:s') . "にログインしました");
});
Flight::onEvent('user.registered', function ($email, $name) {
- echo "$email宛にメールを送信しました: ようこそ、$nameさん!";
+ echo "$emailにメールを送信しました: ようこそ、$name!";
});
```
@@ -165,17 +165,17 @@ Flight::route('/login', function () {
Flight::start();
```
-- **長所**:`index.php`がルーティングに集中できる、論理的にイベントを整理、見つけやすく編集しやすい。
-- **短所**:若干の構造的な追加があり、小さなアプリには過剰に感じることも。
+- **利点**:`index.php`をルーティングに集中させ、イベントを論理的に整理し、見つけやすく編集しやすくする。
+- **欠点**:小さなアプリでは過剰に感じるかもしれない、わずかな構造が追加される。
-### オプション 3: トリガー近くに
-別のアプローチは、トリガーされる場所の近くでイベントを登録することです。コントローラーやルート定義の中で行います。これは、イベントがアプリの特定の部分に特有である場合に効果的です。
+### オプション3: トリガーされる近くに
+別のアプローチは、コントローラーやルート定義の内部のように、トリガーされる近くにイベントを登録することです。これは、イベントがアプリの一部に特定のものである場合にうまく機能します。
```php
Flight::route('/signup', function () {
// ここでイベントを登録
Flight::onEvent('user.registered', function ($email) {
- echo "$email宛にようこそメールが送信されました!";
+ echo "$emailにようこそメールを送信しました!";
});
$email = 'jane@example.com';
@@ -183,25 +183,25 @@ Flight::route('/signup', function () {
echo "サインアップしました!";
});
```
-- **長所**:関連するコードを一緒に保つ、孤立した機能に良い。
-- **短所**:イベント登録が散在し、すべてのイベントを一度に見るのが難しくなる; 慎重でないと重複登録のリスクがあります。
+- **利点**:関連するコードをまとめて保持し、孤立した機能に適しています。
+- **欠点**:イベントの登録が散らばり、すべてのイベントを一度に確認するのが難しくなり、注意を怠ると重複登録のリスクがある。
### Flightのベストプラクティス
-- **シンプルに始める**:小さなアプリでは、`index.php`にイベントを配置します。これが迅速でFlightのミニマリズムに沿っています。
-- **スマートに成長する**:アプリが拡大する場合(例:5-10のイベント以上)、`app/config/events.php`ファイルを使用します。これはルートを整理するような自然なステップであり、複雑なフレームワークを追加することなくコードをすっきり保ってくれます。
-- **過剰設計を避ける**:アプリが巨大になるまで、完全な「イベントマネージャ」クラスやディレクトリを作成しないでください—Flightはシンプルさを重視しているので、軽量に保ってください。
+- **シンプルから始める**:小さなアプリの場合、イベントを`index.php`に置く。迅速で、Flightのミニマリズムに合う。
+- **賢く成長する**:アプリが拡張するにつれて(例:5-10のイベント以上)、`app/config/events.php`ファイルを使用する。ルートを整理するのと同様の自然なステップであり、コードをきれいに保ちつつも複雑なフレームワークを追加しない。
+- **過剰設計を避ける**:アプリが巨大になるまでは、完全な「イベントマネージャー」クラスやディレクトリは作成しないでください—Flightはシンプルさを重視しているため、軽量に保つこと。
### ヒント:目的別にグループ化
-`events.php`内で、関連するイベント(例:すべてのユーザー関連イベントを一緒に)をコメントでグループ化します:
+`events.php`内では、関連するイベントをグループ化(例:すべてのユーザー関連のイベントを一緒に)し、明確さのためにコメントを追加します:
```php
// app/config/events.php
// ユーザーイベント
Flight::onEvent('user.login', function ($username) {
- error_log("$username がログインしました");
+ error_log("$usernameがログインしました");
});
Flight::onEvent('user.registered', function ($email) {
- echo "$emailへようこそ!";
+ echo "$emailにようこそ!";
});
// ページイベント
@@ -210,80 +210,86 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-この構造はスケールしやすく、初心者にも優しいです。
+この構造はうまくスケールし、初心者にも優しいです。
## 初心者向けの例
-いくつかの実世界のシナリオを通じて、イベントがどのように機能し、なぜ役立つのかを示しましょう。
+イベントがどのように機能し、なぜ役立つのかを示すために、いくつかの実際のシナリオを見てみましょう。
-### 例 1: ユーザーログインのロギング
+### 例1: ユーザーログインのログ記録
```php
-// ステップ 1: リスナーを登録
+// ステップ1: リスナーを登録
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username が $time にログインしました");
+ error_log("$usernameが$timeにログインしました");
});
-// ステップ 2: アプリ内でトリガーする
+// ステップ2: アプリ内でトリガーする
Flight::route('/login', function () {
- $username = 'bob'; // これはフォームから来たと仮定
+ $username = 'bob'; // フォームから取得されると仮定
Flight::triggerEvent('user.login', $username);
echo "こんにちは、$username!";
});
```
-**なぜ役立つのか**:ログインコードはロギングのことを考える必要がなく、ただイベントをトリガーします。後で、他のリスナー(例:ウェルカムメールを送信)を追加できるのです。
+**なぜこれは役立つのか**:ログインコードはロギングについて知る必要はありません—それはイベントをトリガーするだけです。後で、より多くのリスナー(例:ウェルカムメールの送信)を追加できますが、ルートを変更する必要はありません。
-### 例 2: 新しいユーザーについて通知
+### 例2: 新しいユーザーについての通知
```php
-// 新しい登録のリスナー
+// 新規登録のリスナー
Flight::onEvent('user.registered', function ($email, $name) {
- // メールを送信するシミュレーション
- echo "$email宛にメールが送信されました: ようこそ、$nameさん!";
+ // メール送信のシミュレーション
+ echo "$emailにメールを送信しました: ようこそ、$name!";
});
-// 誰かがサインアップするときにトリガー
+// 誰かがサインアップしたときにトリガー
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "サインアップありがとうございました!";
+ echo "サインアップありがとう!";
});
```
-**なぜ役立つのか**:サインアップのロジックはユーザーの作成に集中し、イベントが通知を処理します。後で、他のリスナー(例:サインアップをログに記録)を追加できます。
+**なぜこれは役立つのか**:サインアップロジックはユーザーを作成することに焦点を当て、イベントが通知を処理します。他の部分も必要に応じて反応できます。
-### 例 3: キャッシュをクリアする
+### 例3: キャッシュのクリア
```php
// キャッシュをクリアするリスナー
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // 該当する場合、セッションキャッシュをクリア
- echo "$pageIdのキャッシュがクリアされました。";
+ unset($_SESSION['pages'][$pageId]); // 適用可能な場合、セッションキャッシュをクリア
+ echo "ページ$pageIdのキャッシュがクリアされました。";
});
// ページが編集されるときにトリガー
Flight::route('/edit-page/(@id)', function ($pageId) {
- // ページを更新したと仮定
+ // ページが更新されたと仮定
Flight::triggerEvent('page.updated', $pageId);
- echo "$pageIdページが更新されました。";
+ echo "ページ$pageIdが更新されました。";
});
```
-**なぜ役立つのか**:編集コードはキャッシングのことを考える必要がなく、更新を信号として発信します。他のアプリの部分が必要に応じて反応できます。
+**なぜこれは役立つのか**:編集コードはキャッシングに関することは気にしません—それは更新を信号します。他のアプリ部分も必要に応じて反応できます。
## ベストプラクティス
-- **イベント名を明確に**:`'user.login'`や`'page.updated'`のように具体的な名前を使用してください。どのような役割か明確になるので。
-- **リスナーをシンプルに保つ**:リスナー内に遅いまたは複雑なタスクを置かないように—アプリを速く保ちます。
-- **イベントをテストする**:手動でトリガーして、リスナーが期待通りに機能することを確認してください。
-- **イベントを適切に使用する**:デカップリングには優れていますが、多すぎるとコードが追いにくくなることがあるため、意味があるときに使用してください。
+- **イベントに明確な名前を付ける**:`'user.login'`や`'page.updated'`のように特定の名前を使用して、何をするかを明確にします。
+- **リスナーをシンプルに保つ**:リスナー内に遅いまたは複雑なタスクを置かないでください—アプリを迅速に保ちます。
+- **イベントをテストする**:手動でトリガーしてリスナーが期待通りに機能することを確認します。
+- **イベントを賢く使用する**:デカップリングに最適ですが、あまりにも多いとコードが見にくくなる可能性があるため、適切な場合にのみ使用します。
-`Flight::onEvent()`と`Flight::triggerEvent()`によるFlight PHPのイベントシステムは、柔軟なアプリケーションを構築するためのシンプルでありながら強力な方法を提供します。アプリの異なる部分がイベントを通じてお互いに話し合うことを可能にすることにより、コードを整理し、再利用可能で、拡張しやすくできます。アクションを記録したり、通知を送信したり、更新を管理したりする際に、ロジックを絡ませることなく行うのに役立ちます。さらに、これらのメソッドをオーバーライドできることで、ニーズに合わせてシステムをカスタマイズする自由があります。最初は単一のイベントから始め、その後アプリの構造がどのように変わっていくかを見てみてください。
+`Flight::onEvent()`と`Flight::triggerEvent()`を使用したFlight PHPのイベントシステムは、柔軟なアプリケーションを構築するためのシンプルで強力な方法を提供します。アプリの異なる部分がイベントを通じて互いに話し合うことを可能にすることで、コードを整理、再利用、拡張しやすいものに保つことができます。アクションのログ記録、通知の送信、更新の管理に関係なく、イベントを使用することで複雑なロジックに干渉することなく実現できます。さらに、これらのメソッドをオーバーライドできることで、必要に応じてシステムをカスタマイズする自由があります。単一のイベントから小さく始めて、アプリの構造がどのように変わるかを見てみましょう!
## ビルトインイベント
-Flight PHPには、フレームワークのライフサイクルにフックするために使用できるいくつかのビルトインイベントがあります。これらのイベントは、リクエスト/レスポンスサイクルの特定のポイントでトリガーされ、特定のアクションが発生したときにカスタムロジックを実行することを可能にします。
-
-### ビルトインイベント一覧
-- `flight.request.received`:リクエストが受信され、解析され、処理されたときにトリガーされます。
-- `flight.route.middleware.before`:beforeミドルウェアが実行された後にトリガーされます。
-- `flight.route.middleware.after`:afterミドルウェアが実行された後にトリガーされます。
-- `flight.route.executed`:ルートが実行され、処理された後にトリガーされます。
-- `flight.response.sent`:レスポンスがクライアントに送信された後にトリガーされます。
\ No newline at end of file
+Flight PHPには、フレームワークのライフサイクルでフックするために使用できるいくつかのビルトインイベントがあります。これらのイベントは、リクエスト/レスポンスサイクルの特定のポイントでトリガーされ、特定のアクションが発生したときにカスタムロジックを実行できます。
+
+### ビルトインイベントリスト
+- **flight.request.received**: `function(Request $request)` リクエストが受信され、解析され、処理されるとトリガーされます。
+- **flight.error**: `function(Throwable $exception)` リクエストライフサイクル中にエラーが発生したときにトリガーされます。
+- **flight.redirect**: `function(string $url, int $status_code)` リダイレクトが開始されたときにトリガーされます。
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` 特定のキーのキャッシュが確認されたときにトリガーされ、キャッシュのヒットまたはミス。
+- **flight.middleware.before**: `function(Route $route)` beforeミドルウェアが実行された後にトリガーされます。
+- **flight.middleware.after**: `function(Route $route)` afterミドルウェアが実行された後にトリガーされます。
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` 任意のミドルウェアが実行された後にトリガーされます。
+- **flight.route.matched**: `function(Route $route)` ルートが一致したときに、まだ実行されていないときにトリガーされます。
+- **flight.route.executed**: `function(Route $route, float $executionTime)` ルートが実行され、処理された後にトリガーされます。`$executionTime`は、ルートを実行するのにかかった時間(コントローラーを呼び出すなど)です。
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` ビューがレンダリングされた後にトリガーされます。`$executionTime`は、テンプレートをレンダリングするのにかかった時間です。**注意:`render`メソッドをオーバーライドする場合は、このイベントを再トリガーする必要があります。**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` レスポンスがクライアントに送信された後にトリガーされます。`$executionTime`は、レスポンスを構築するのにかかった時間です。
\ No newline at end of file
diff --git a/content/v3/ko/awesome-plugins/apm.md b/content/v3/ko/awesome-plugins/apm.md
new file mode 100644
index 0000000..4f8eb88
--- /dev/null
+++ b/content/v3/ko/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM Documentation
+
+FlightPHP APM에 오신 것을 환영합니다—귀하의 앱의 개인 성능 코치! 이 가이드는 FlightPHP와 함께 애플리케이션 성능 모니터링(APM)을 설정하고, 사용하고, 마스터하기 위한 로드맵입니다. 느린 요청을 추적하든, 단순히 지연 차트에 대해 Geek-ish하게 이야기하든, 저희가 도와드리겠습니다. 앱을 더 빠르게, 사용자를 더 행복하게, 디버깅 세션을 더 수월하게 만들어 봅시다!
+
+## APM이 중요한 이유
+
+상상해 보세요: 귀하의 앱은 바쁜 레스토랑입니다. 주문 소요 시간을 추적하거나 주방의 문제를 파악할 방법이 없으면, 고객이 왜 불만을 품고 떠나는지 추측할 수밖에 없습니다. APM은 당신의 수석 요리사입니다—진입 요청부터 데이터베이스 쿼리까지 모든 단계를 지켜보고, 당신을 느리게 하는 무언가를 플래그합니다. 느린 페이지는 사용자를 잃게 만듭니다(연구에 따르면 사이트가 3초 이상 걸리면 53%가 이탈한다고 합니다!), 그리고 APM은 이러한 문제를 *피해*가기 전에 포착하도록 도와줍니다. 이는 사전 예방적인 안정성입니다—“왜 이게 깨졌지?”라는 순간은 줄어들고, “이렇게 매끄럽게 작동하네!”라는 승리는 더 많아집니다.
+
+## 설치
+
+Composer로 시작하세요:
+
+```bash
+composer require flightphp/apm
+```
+
+필요한 사항:
+- **PHP 7.4+**: 현대 PHP를 지원하면서 LTS 리눅스 배포판과의 호환성을 유지합니다.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: 저희가 강화하고 있는 경량 프레임워크입니다.
+
+## 시작하기
+
+APM의 멋진 세계로 들어가는 단계별 절차입니다:
+
+### 1. APM 등록하기
+
+이 코드를 `index.php` 또는 `services.php` 파일에 추가하여 추적을 시작하세요:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**여기서 무슨 일이 일어나고 있나요?**
+- `LoggerFactory::create()`는 구성 파일을 가져오고(곧 자세히 설명할 예정) 로거를 설정합니다—기본적으로 SQLite입니다.
+- `Apm`이 주인공입니다—Flight의 이벤트(요청, 경로, 오류 등)를 청취하고 메트릭을 수집합니다.
+- `bindEventsToFlightInstance($app)`는 모든 것을 귀하의 Flight 앱에 연결합니다.
+
+**전문 팁: 샘플링**
+앱이 바쁘면 모든 요청을 기록하면 과부하가 걸릴 수 있습니다. 샘플 비율을 사용하세요(0.0에서 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // 요청의 10%를 기록합니다
+```
+
+이렇게 하면 성능은 날카롭게 유지하면서도 확실한 데이터를 제공받을 수 있습니다.
+
+### 2. 설정하기
+
+`.runway-config.json`을 생성하려면 이 명령을 실행하세요:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**이 명령의 역할은?**
+- 원시 메트릭이 어디에서 오는지(소스)와 처리된 데이터가 어디로 가는지(대상)를 묻는 마법사를 실행합니다.
+- 기본값은 SQLite입니다—예를 들어, 소스는 `sqlite:/tmp/apm_metrics.sqlite`, 그리고 대상은 다른 것입니다.
+- 최종적으로 다음과 같은 구성이 생성됩니다:
+ ```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"
+ }
+ }
+ ```
+
+**왜 두 개의 위치일까요?**
+원시 메트릭은 빠르게 쌓입니다(필터링되지 않은 로그를 생각해 보세요). 작업자는 이를 대시보드용으로 구조화된 대상으로 처리합니다. 모든 것을 깔끔하게 유지합니다!
+
+### 3. 작업자를 통해 메트릭 처리하기
+
+작업자는 원시 메트릭을 대시보드 준비가 된 데이터로 변환합니다. 한 번 실행해 보세요:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**이 작업이 무엇을 하고 있나요?**
+- 소스(예: `apm_metrics.sqlite`)에서 읽습니다.
+- 기본 배치 크기인 100개의 메트릭을 대상으로 처리합니다.
+- 완료되면 멈추거나 남아 있는 메트릭이 없으면 멈춥니다.
+
+**계속 실행하기**
+실시간 앱의 경우 지속적인 처리가 필요합니다. 다음과 같은 옵션이 있습니다:
+
+- **데몬 모드**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ 들어오는 대로 메트릭을 처리하며 영원히 실행됩니다. 개발이나 작은 설정에 적합합니다.
+
+- **크론탭**:
+ 크론탭에 이 코드를 추가하세요(`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`로 재연결
+ ```
+ 로그아웃해도 계속 실행됩니다.
+
+- **사용자 정의 조정**:
+ ```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분 후 종료합니다.
+
+**왜 신경 써야 할까요?**
+작업자가 없으면 대시보드는 비어 있습니다. 이는 원시 로그와 실행 가능한 통찰력 사이의 다리입니다.
+
+### 4. 대시보드 시작하기
+
+귀하의 앱의 주요 성능 지표를 확인하십시오:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**이 명령의 역할은?**
+- `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`: PHP가 PATH에 없으면 경로를 지정합니다.
+
+브라우저에서 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`로 설정합니다.
+
+#### 다른 대시보드가 필요하신가요?
+
+원하는 경우, 직접 대시보드를 구축할 수 있습니다! 데이터를 자신의 대시보드에 표시하는 방법에 대한 아이디어는 `vendor/flightphp/apm/src/apm/presenter` 디렉토리를 확인해보세요!
+
+## 대시보드 기능
+
+대시보드는 귀하의 APM HQ입니다—다음 내용을 볼 수 있습니다:
+
+- **요청 로그**: 타임스탬프, URL, 응답 코드 및 총 시간을 가진 모든 요청. 세부 정보를 클릭하면 미들웨어, 쿼리 및 오류를 확인할 수 있습니다.
+- **느린 요청**: 시간을 잡아먹는 상위 5개의 요청(예: “/api/heavy”는 2.5초).
+- **느린 경로**: 평균 시간에 따른 상위 5개 경로—패턴을 파악하는 데 유용합니다.
+- **오류 비율**: 실패하는 요청의 비율(예: 2.3% 500 오류).
+- **지연 백분위수**: 95번째(p95) 및 99번째(p99) 응답 시간—최악의 경우를 미리 알 수 있습니다.
+- **응답 코드 차트**: 시간에 따른 200, 404, 500 오류를 시각화합니다.
+- **긴 쿼리/미들웨어**: 상위 5개의 느린 데이터베이스 호출 및 미들웨어 레이어.
+- **캐시 적중/실패**: 캐시가 얼마나 자주 도움을 주는지.
+
+**추가 기능**:
+- “지난 1시간”, “지난 1일”, 또는 “지난 1주”로 필터링.
+- 늦은 밤 세션을 위해 다크 모드 전환.
+
+**예시**:
+`/users`에 대한 요청은 다음과 같이 표시될 수 있습니다:
+- 총 시간: 150ms
+- 미들웨어: `AuthMiddleware->handle` (50ms)
+- 쿼리: `SELECT * FROM users` (80ms)
+- 캐시: `user_list`에서 적중 (5ms)
+
+## 사용자 지정 이벤트 추가하기
+
+API 호출이나 결제 프로세스와 같은 어떤 것이든 추적하세요:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**어디에 표시되나요?**
+대시보드의 요청 세부정보 아래 “사용자 지정 이벤트”에서 확인할 수 있습니다—예쁘게 JSON 형식으로 확장 가능합니다.
+
+**사용 사례**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+이제 그 API가 귀하의 앱을 느리게 만드는지 알 수 있습니다!
+
+## 데이터베이스 모니터링
+
+다음과 같이 PDO 쿼리를 추적하세요:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**얻는 것**:
+- 쿼리 텍스트 (예: `SELECT * FROM users WHERE id = ?`)
+- 실행 시간 (예: 0.015초)
+- 행 수 (예: 42)
+
+**알림**:
+- **선택 사항**: DB 추적이 필요하지 않으면 건너뛰세요.
+- **PdoWrapper 전용**: 코어 PDO는 아직 연결되지 않았습니다—조만간 업데이트 예정입니다!
+- **성능 경고**: DB가 많은 사이트에서 모든 쿼리를 기록하기는 느려질 수 있습니다. 샘플링(`$Apm = new Apm($ApmLogger, 0.1)`)을 사용하여 부하를 줄이세요.
+
+**예시 출력**:
+- 쿼리: `SELECT name FROM products WHERE price > 100`
+- 시간: 0.023초
+- 행: 15
+
+## 작업자 옵션
+
+원하는 대로 작업자를 조정하세요:
+
+- `--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개의 메트릭을 처리합니다.
+
+## 문제 해결
+
+막히셨나요? 다음을 시도해 보세요:
+
+- **대시보드 데이터가 없나요?**
+ - 작업자가 실행되고 있나요? `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 로그를 확인하세요.
+
+- **대시보드 시작이 안 되나요?**
+ - 8001 포트가 사용 중인가요? `--port 8080`을 사용하세요.
+ - PHP를 찾지 못하나요? `--php-path /usr/bin/php`를 사용하세요.
+ - 방화벽이 차단하나요? 포트를 열거나 `--host localhost`를 사용하세요.
+
+- **너무 느린가요?**
+ - 샘플 비율을 낮추세요: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - 배치 크기를 줄이세요: `--batch_size 20`.
\ 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 9ce88c6..efeb1e6 100644
--- a/content/v3/ko/awesome-plugins/awesome_plugins.md
+++ b/content/v3/ko/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
# 멋진 플러그인
-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) - FlightPHP와 함께 OpenAPI Spec을 사용하는 방법에 대해 Daniel Schreiber가 작성한 블로그 게시물로, 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) - API 우선 접근 방식을 사용하여 FlightPHP로 API를 구축하는 방법에 대해 Daniel Schreiber가 작성한 블로그 게시물이다.
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서를 생성하는 데 도움이 되는 훌륭한 도구이다. 사용이 매우 쉽고 필요에 맞게 사용자 정의할 수 있다. Swagger 문서를 생성하는 데 도움이 되는 PHP 라이브러리이다.
+
+## 애플리케이션 성능 모니터링 (APM)
+
+애플리케이션 성능 모니터링(APM)은 모든 애플리케이션에 필수적이다. 이는 애플리케이션의 성능을 이해하고 병목 지점을 찾는 데 도움을 준다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있다.
+- beta[flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하기 위해 사용할 수 있는 간단한 APM 라이브러리이다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움을 줄 수 있다.
## 인증/권한 부여
-인증 및 권한 부여는 누가 무엇에 접근할 수 있는지 제어가 필요한 모든 애플리케이션에 매우 중요하다.
+인증과 권한 부여는 어떤 애플리케이션에서 접근할 수 있는 것을 제어해야 하는 필수 요소이다.
-- 공식 [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight 권한 라이브러리. 이 라이브러리는 귀하의 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법이다.
+- official [flightphp/permissions](/awesome-plugins/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는 귀하의 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와 함께 사용할 수 있는 전체 기능의 오류 처리기이다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널이 있다. 또한 매우 쉽게 확장하고 사용자 정의 패널을 추가할 수 있다.
-- [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이다.
-- 공식 [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - 코어의 일부인 공식 Flight PDO 래퍼. 이는 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움이 되는 간단한 래퍼이다. ORM이 아니다.
-- 공식 [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/매퍼. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 데 유용한 작은 라이브러리이다.
-- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트에 대한 모든 데이터베이스 변경 사항을 추적하는 플러그인이다.
+- official [flightphp/core PdoWrapper](/awesome-plugins/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) - 이는 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리이다. 암호화 및 복호화를 시작하는 것은 비교적 간단하다.
+- [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에는 그다지 유용하지 않지만, 웹 애플리케이션을 구축하는 데 있어 상태 및 로그인 정보를 유지하는 데 필수적일 수 있다.
-- 공식 [flightphp/session](/awesome-plugins/session) - 공식 Flight 세션 라이브러리. 이는 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리이다. PHP의 내장 세션 처리 기능을 사용한다.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자(비차단, 플래시, 세그먼트, 세션 암호화). 선택적인 세션 데이터의 암호화/복호화에 PHP open_ssl을 사용한다.
+- official [flightphp/session](/awesome-plugins/session) - 공식 Flight 세션 라이브러리. 이는 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리이다. PHP의 내장 세션 처리를 사용한다.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자(비차단, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용한다.
-## 템플릿화
+## 템플릿
-템플릿화는 UI가 있는 모든 웹 애플리케이션의 핵심이다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있다.
+템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심이다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있다.
-- 사용 중단됨 [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 문법에 더 가깝다. 또한 확장하기 쉽고 자신만의 필터와 함수를 추가할 수 있다.
-## 기여하기
+## 기여
-나누고 싶은 플러그인이 있습니까? 목록에 추가하려면 풀 리퀘스트를 제출하세요!
\ No newline at end of file
+공유하고 싶은 플러그인이 있으신가요? 목록에 추가하기 위해 풀 리퀘스트를 제출하세요!
\ No newline at end of file
diff --git a/content/v3/ko/awesome-plugins/tracy_extensions.md b/content/v3/ko/awesome-plugins/tracy_extensions.md
index 3b70067..4a94b2a 100644
--- a/content/v3/ko/awesome-plugins/tracy_extensions.md
+++ b/content/v3/ko/awesome-plugins/tracy_extensions.md
@@ -1,31 +1,32 @@
-## Tracy 체크 패널 확장
+Tracy Flight 패널 확장
+=====
-이것은 Flight와 함께 작업하는 것을 좀 더 풍부하게 만들기 위한 일련의 확장입니다.
+이것은 Flight와 함께 작업하는 것을 조금 더 풍부하게 만드는 확장 세트입니다.
- Flight - 모든 Flight 변수를 분석합니다.
-- Database - 페이지에서 실행된 모든 쿼리를 분석합니다 (데이터베이스 연결을 올바르게 초기화했을 경우)
-- Request - 모든 `$_SERVER` 변수를 분석하고 모든 전역 페이로드를 검토합니다 (`$_GET`, `$_POST`, `$_FILES`)
-- Session - 세션이 활성화된 경우 모든 `$_SESSION` 변수를 분석합니다.
+- Database - 페이지에서 실행된 모든 쿼리를 분석합니다 (데이터베이스 연결을 올바르게 시작한 경우).
+- Request - 모든 `$_SERVER` 변수를 분석하고 모든 전역 페이로드(`$_GET`, `$_POST`, `$_FILES`)를 검사합니다.
+- Session - 세션이 활성 상태인 경우 모든 `$_SESSION` 변수를 분석합니다.
-이것은 패널입니다
+이것이 패널입니다.

-그리고 각 패널은 응용 프로그램에 대해 매우 유용한 정보를 표시합니다!
+각 패널은 애플리케이션에 대한 매우 유용한 정보를 표시합니다!



-[여기](https://github.com/flightphp/tracy-extensions)를 클릭하여 코드를 확인하세요.
+코드를 보려면 [여기](https://github.com/flightphp/tracy-extensions)를 클릭하세요.
설치
-------
-`composer require flightphp/tracy-extensions --dev`를 실행하면 됩니다!
+`composer require flightphp/tracy-extensions --dev`를 실행하면 준비가 완료됩니다!
구성
-------
-시작하려면 할 필요가 있는 구성은 매우 적습니다. 이를 사용하기 전에 Tracy 디버거를 초기화해야 합니다. [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide)를 사용하세요:
+시작하려면 구성해야 할 사항이 거의 없습니다. 사용하기 전에 Tracy 디버거를 시작해야 합니다 [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // 이것은 false여야 Tracy가 실제로 렌더링하지 못합니다 :(
+ // 이 값은 false여야 합니다. 그렇지 않으면 Tracy가 실제로 렌더링할 수 없습니다 :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -87,7 +89,7 @@ Flight::start();
### Latte
-프로젝트에 Latte가 설치되어 있는 경우 Latte 패널을 사용하여 템플릿을 분석할 수 있습니다. 두 번째 매개변수의 `latte` 키로 `TracyExtensionLoader` 생성자에 Latte 인스턴스를 전달할 수 있습니다.
+프로젝트에 Latte가 설치되어 있는 경우, Latte 패널을 사용하여 템플릿을 분석할 수 있습니다. 생성자의 두 번째 매개변수에 `latte` 키와 함께 Latte 인스턴스를 전달할 수 있습니다.
```php
@@ -100,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // 이곳에 Latte 패널을 Tracy에 추가합니다
+ // 여기서 Latte 패널을 Tracy에 추가합니다.
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // 이것은 false여야 Tracy가 실제로 렌더링하지 못합니다 :(
+ // 이 값은 false여야 합니다. 그렇지 않으면 Tracy가 실제로 렌더링할 수 없습니다 :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/ko/learn/events.md b/content/v3/ko/learn/events.md
index 1da6ab2..e901bf9 100644
--- a/content/v3/ko/learn/events.md
+++ b/content/v3/ko/learn/events.md
@@ -1,154 +1,154 @@
# Flight PHP의 이벤트 시스템 (v3.15.0+)
-Flight PHP는 애플리케이션에서 사용자 정의 이벤트를 등록하고 트리거할 수 있는 경량화되고 직관적인 이벤트 시스템을 소개합니다. `Flight::onEvent()` 및 `Flight::triggerEvent()`의 추가로, 이제 애플리케이션의 주요 생명 주기 순간에 연결하거나 코드를 더욱 모듈화하고 확장할 수 있도록 자체 이벤트를 정의할 수 있습니다. 이러한 메서드는 Flight의 **구성 가능한 메서드**의 일부로, 필요에 따라 동작을 재정의할 수 있습니다.
+Flight PHP는 애플리케이션에서 사용자 정의 이벤트를 등록하고 트리거할 수 있는 경량의 직관적인 이벤트 시스템을 도입합니다. `Flight::onEvent()` 및 `Flight::triggerEvent()`의 추가로, 이제 앱의 생명 주기의 주요 순간에 훅을 걸거나 코드를 보다 모듈화하고 확장 가능하도록 자신만의 이벤트를 정의할 수 있습니다. 이러한 메서드는 Flight의 **맵 가능한 메서드**의 일부로, 필요에 맞게 동작을 재정의할 수 있습니다.
-이 가이드는 이벤트와 관련하여 알아야 할 모든 것을 다루며, 그 가치, 사용 방법 및 초보자가 그 힘을 이해하도록 돕는 실제 예제를 포함합니다.
+이 가이드는 이벤트를 시작하는 데 필요한 모든 내용을 다룹니다. 여기에는 이벤트가 왜 중요한지, 어떻게 사용하는지, 초보자가 그 힘을 이해하는 데 도움이 되는 실용적인 예제가 포함됩니다.
-## 왜 이벤트를 사용할까요?
+## 왜 이벤트를 사용해야 할까요?
-이벤트는 애플리케이션의 서로 다른 부분을 분리하여 서로에게 지나치게 의존하지 않도록 할 수 있습니다. 이러한 분리는 종종 **디커플링**이라고 불리며, 코드 업데이트, 확장 또는 디버깅을 쉽게 만듭니다. 모든 것을 하나의 큰 덩어리로 작성하는 대신, 특정 행동(이벤트)에 반응하는 더 작고 독립적인 조각으로 논리를 분리할 수 있습니다.
+이벤트는 애플리케이션의 다양한 부분을 분리하여 서로에게 지나치게 의존하지 않도록 허용합니다. 이러한 분리—종종 **디커플링**이라고 불림—는 코드를 업데이트, 확장 또는 디버그하기 쉽게 만듭니다. 모든 것을 하나의 큰 덩어리로 쓰는 대신, 특정 행동(이벤트)에 응답하는 더 작고 독립적인 조각으로 논리를 나눌 수 있습니다.
-블로그 앱을 만들고 있다고 상상해보세요:
-- 사용자가 댓글을 게시할 때, 다음을 수행할 수 있습니다:
- - 댓글을 데이터베이스에 저장합니다.
- - 블로그 소유자에게 이메일을 보냅니다.
- - 보안을 위해 작업을 기록합니다.
+블로그 앱을 구축하고 있다고 상상해 보세요:
+- 사용자가 댓글을 게시할 때, 다음을 원할 수 있습니다:
+ - 데이터베이스에 댓글 저장.
+ - 블로그 소유자에게 이메일 전송.
+ - 보안을 위해 행동 기록.
-이벤트 없이 모든 작업을 하나의 함수에 밀어넣어야 합니다. 이벤트가 있으면 이들을 나누어 하나의 파트가 댓글을 저장하고, 또 다른 파트가 `'comment.posted'`와 같은 이벤트를 트리거하며, 별도의 리스너가 이메일과 로깅을 처리합니다. 이를 통해 코드를 더 깔끔하게 유지하고, 코어 논리를 건드리지 않고도 알림과 같은 기능을 추가하거나 제거할 수 있습니다.
+이벤트 없이 모든 것을 하나의 함수에 담을 수 있지만, 이벤트를 사용하면 나누어 처리할 수 있습니다: 한 부분은 댓글을 저장하고, 다른 부분은 `'comment.posted'`와 같은 이벤트를 트리거하며, 별도의 리스너가 이메일과 로깅을 처리합니다. 이렇게 하면 코드를 깨끗하게 유지하면서 알림과 같은 기능을 추가하거나 제거할 수 있습니다.
-### 일반적인 용도
-- **로깅**: 로그인 또는 오류와 같은 작업을 기록하여 기본 코드를 혼잡하게 만들지 않습니다.
+### 일반적인 사용 사례
+- **로깅**: 로그인이나 오류와 같은 행동을 기록하되, 기본 코드를 혼잡하게 하지 않습니다.
- **알림**: 어떤 일이 발생할 때 이메일이나 경고를 보냅니다.
- **업데이트**: 캐시를 새로 고치거나 다른 시스템에 변경 사항을 알립니다.
-## 이벤트 리스너 등록
+## 이벤트 리스너 등록하기
-이벤트를 듣기 위해 `Flight::onEvent()`를 사용하세요. 이 메서드는 이벤트가 발생할 때 어떤 일이 발생해야 하는지를 정의할 수 있게 해줍니다.
+이벤트를 수신하려면 `Flight::onEvent()`를 사용하십시오. 이 메서드는 이벤트가 발생할 때 어떤 일이 일어나야 하는지 정의할 수 있게 해줍니다.
### 구문
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: 이벤트 이름 (예: `'user.login'`).
-- `$callback`: 이벤트가 트리거될 때 실행할 함수.
+- `$event`: 이벤트에 대한 이름 (예: `'user.login'`).
+- `$callback`: 이벤트가 트리거될 때 실행할 함수입니다.
### 작동 방식
-이벤트에 "구독"하려면 Flight에 발생했을 때 수행할 작업을 알립니다. 콜백은 이벤트 트리거에서 전달된 인수를 받을 수 있습니다.
+이벤트에 "구독"함으로써 Flight에 일이 발생할 때 무엇을 해야 하는지 알려줍니다. 콜백은 이벤트 트리거에서 전달된 인수를 받을 수 있습니다.
-Flight의 이벤트 시스템은 동기식으로, 이는 각 이벤트 리스너가 순차적으로 실행됨을 의미합니다. 이벤트를 트리거할 때, 해당 이벤트에 등록된 모든 리스너가 완료될 때까지 실행됩니다. 이는 비동기 이벤트 시스템과 다르기 때문에 이해하는 것이 중요합니다.
+Flight의 이벤트 시스템은 동기식입니다. 즉, 각 이벤트 리스너는 순차적으로 하나씩 실행됩니다. 이벤트를 트리거하면 해당 이벤트에 등록된 모든 리스너가 완료될 때까지 실행됩니다. 이는 비동기 이벤트 시스템과 다르므로 중요한 이해가 필요합니다. 비동기 시스템에서는 리스너가 병렬로 또는 나중에 실행될 수 있습니다.
-### 간단한 예제
+### 간단한 예
```php
Flight::onEvent('user.login', function ($username) {
- echo "Welcome back, $username!";
+ echo "다시 오신 것을 환영합니다, $username!";
});
```
-여기서 `'user.login'` 이벤트가 트리거되면 사용자의 이름으로 인사합니다.
+여기서 `'user.login'` 이벤트가 트리거될 때, 사용자의 이름으로 인사합니다.
### 주요 사항
-- 같은 이벤트에 여러 리스너를 추가할 수 있으며, 등록한 순서대로 실행됩니다.
-- 콜백은 함수, 익명 함수 또는 클래스의 메서드가 될 수 있습니다.
+- 동일한 이벤트에 여러 리스너를 추가할 수 있으며, 등록한 순서대로 실행됩니다.
+- 콜백은 함수, 익명 함수, 또는 클래스의 메서드일 수 있습니다.
## 이벤트 트리거하기
-이벤트가 발생하도록 하려면 `Flight::triggerEvent()`를 사용하세요. 이 메서드는 Flight에 등록된 모든 리스너를 실행하도록 지시하며, 제공하는 데이터를 전달합니다.
+이벤트를 발생시키려면 `Flight::triggerEvent()`를 사용하세요. 이는 Flight에게 해당 이벤트에 등록된 모든 리스너를 실행하도록 알리며, 제공한 데이터를 전달합니다.
### 구문
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: 트리거하려는 이벤트 이름(등록된 이벤트와 일치해야 함).
-- `...$args`: 리스너에 전달할 선택적 인수 (아무 개수의 인수가 될 수 있음).
+- `$event`: 트리거할 이벤트 이름(등록된 이벤트와 일치해야 함).
+- `...$args`: 리스너에 전송할 선택적 인수(임의의 수의 인수를 보낼 수 있음).
-### 간단한 예제
+### 간단한 예
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-이것은 `'user.login'` 이벤트를 트리거하고, 이전에 정의한 리스너에 `'alice'`를 전달하여 `Welcome back, alice!`를 출력합니다.
+이것은 `'user.login'` 이벤트를 트리거하고 이전에 정의한 리스너에 `'alice'`를 전달하여 출력합니다: `다시 오신 것을 환영합니다, alice!`.
### 주요 사항
-- 리스너가 등록되지 않으면 아무 일도 발생하지 않습니다—당신의 앱은 깨지지 않습니다.
-- 스프레드 연산자(`...`)를 사용하여 여러 인수를 유연하게 전달합니다.
+- 리스너가 등록되어 있지 않으면 아무 일도 일어나지 않으며, 앱이 고장 나지 않습니다.
+- 스프레드 연산자(`...`)를 사용하여 여러 인수를 유연하게 전달하십시오.
-### 이벤트 리스너 등록
+### 이벤트 리스너 등록하기
...
**추가 리스너 중지**:
-리스너가 `false`를 반환하면 해당 이벤트의 추가 리스너는 실행되지 않습니다. 이는 특정 조건에 따라 이벤트 체인을 중단할 수 있게 해줍니다. 리스너의 순서가 중요하며, `false`를 반환하는 첫 번째 리스너가 나머지 실행을 중지합니다.
+리스너가 `false`를 반환하면, 해당 이벤트에 대해 추가 리스너가 실행되지 않습니다. 이는 특정 조건에 따라 이벤트 체인을 중지할 수 있습니다. 리스너의 순서가 중요하므로, 첫 번째 리스너가 `false`를 반환하면 나머지가 실행되지 않습니다.
-**예제**:
+**예**:
```php
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // 후속 리스너 중단
+ return false; // 후속 리스너 중지
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // 이는 결코 보내지지 않음
+ sendWelcomeEmail($username); // 이건 전송되지 않음
});
```
-## 이벤트 메서드 재정의
+## 이벤트 메서드 재정의하기
-`Flight::onEvent()` 및 `Flight::triggerEvent()`는 [확장 가능](/learn/extending)하며, 작동 방식을 재정의할 수 있습니다. 이는 로그 추가나 이벤트 배포 방식을 변경하고 싶어하는 고급 사용자를 위한 훌륭한 기능입니다.
+`Flight::onEvent()` 및 `Flight::triggerEvent()`는 [확장 가능](/learn/extending)하므로, 작동 방식을 재정의할 수 있습니다. 이는 이벤트 시스템을 사용자 정의하고자 하는 고급 사용자에게 유용합니다. 예를 들어 로깅을 추가하거나 이벤트가 전달되는 방식을 변경할 수 있습니다.
-### 예제: `onEvent` 사용자 정의
+### 예: `onEvent` 사용자 정의
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // 모든 이벤트 등록 로그
- error_log("새 이벤트 리스너가 추가되었습니다: $event");
- // 기본 동작 호출 (내부 이벤트 시스템 가정)
+ // 모든 이벤트 등록을 기록합니다
+ error_log("추가된 새로운 이벤트 리스너: $event");
+ // 기본 동작을 호출합니다 (내부 이벤트 시스템을 가정)
Flight::_onEvent($event, $callback);
});
```
-이제 이벤트를 등록할 때마다 로그를 남기고 진행합니다.
+이제 이벤트를 등록할 때마다 로그가 기록되고 진행됩니다.
-### 왜 재정의할까요?
+### 왜 재정의하나요?
- 디버깅 또는 모니터링 추가.
- 특정 환경에서 이벤트 제한 (예: 테스트 중 비활성화).
- 다른 이벤트 라이브러리와 통합.
-## 이벤트를 어디에 두어야 하나요
+## 이벤트를 어디에 두어야 할까요?
-초보자로서 궁금할 수 있습니다: *내 앱에서 모든 이벤트를 어디에 등록해야 할까요?* Flight의 단순함은 엄격한 규칙이 없다는 의미입니다—프로젝트에 적합한 곳에 배치하면 됩니다. 그러나 정리된 상태를 유지하는 것은 앱이 성장함에 따라 코드를 유지 관리하는 데 도움이 됩니다. 다음은 Flight의 경량 속성에 맞춘 몇 가지 실제 선택과 모범 사례입니다.
+초보자로서 궁금할 수 있습니다: *애플리케이션에서 모든 이벤트를 어디에 등록하나요?* Flight의 단순성은 엄격한 규칙이 없음을 의미합니다—프로젝트에 맞는 곳에 두시면 됩니다. 그러나 제외하면 이벤트를 정리하면 코드 유지 관리가 용이해집니다. 다음은 Flight의 경량 특성에 맞춘 몇 가지 실용적인 옵션 및 모범 사례입니다.
-### 옵션 1: 기본 `index.php`에
-작은 앱이나 빠른 프로토타입의 경우 `index.php` 파일 내에서 경로와 함께 이벤트를 등록할 수 있습니다. 이것은 모든 것을 한 곳에 두어 단순함이 우선일 때 잘 작동합니다.
+### 옵션 1: 메인 `index.php`에
+작은 앱이나 빠른 프로토타입의 경우 `index.php` 파일에 이벤트를 등록할 수 있습니다. 이는 단순성이 우선인 경우 모든 것을 한 곳에 유지할 수 있습니다.
```php
require 'vendor/autoload.php';
// 이벤트 등록
Flight::onEvent('user.login', function ($username) {
- error_log("$username logged in at " . date('Y-m-d H:i:s'));
+ error_log("$username의 로그인 시간: " . date('Y-m-d H:i:s'));
});
-// 라우트 정의
+// 경로 정의
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Logged in!";
+ echo "로그인되었습니다!";
});
Flight::start();
```
- **장점**: 간단함, 추가 파일 없음, 작은 프로젝트에 적합.
-- **단점**: 앱이 커지면서 더 많은 이벤트와 경로가 생기면 혼잡해질 수 있음.
+- **단점**: 이벤트와 경로가 많아짐에 따라 복잡해질 수 있음.
### 옵션 2: 별도의 `events.php` 파일
-약간 더 큰 앱의 경우 이벤트 등록을 `app/config/events.php`와 같은 전용 파일로 이동하는 것을 고려하세요. 이 파일을 `index.php`에서 라우트 전에 포함하세요. 이는 Flight 프로젝트에서 라우트가 종종 `app/config/routes.php`에 조직되는 방식과 유사합니다.
+조금 더 큰 앱의 경우, 이벤트 등록을 `app/config/events.php`와 같은 전용 파일로 이동하는 것을 고려하세요. 이 파일을 `index.php`에 경로 정의 전에 포함하십시오. 이는 Flight 프로젝트의 `app/config/routes.php`에서 경로를 구성하는 방식과 유사합니다.
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username logged in at " . date('Y-m-d H:i:s'));
+ error_log("$username의 로그인 시간: " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
- echo "Email sent to $email: Welcome, $name!";
+ echo "$email로 이메일 전송: $name님, 환영합니다!";
});
```
@@ -160,48 +160,48 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Logged in!";
+ echo "로그인되었습니다!";
});
Flight::start();
```
-- **장점**: `index.php`를 라우팅에 집중하게 하고, 이벤트를 논리적으로 조직하여 찾고 편집하기 쉬움.
-- **단점**: 약간의 구조를 추가하며, 매우 작은 앱에서는 과한 느낌이 들 수 있음.
+- **장점**: `index.php`가 라우팅에 집중하도록 유지, 이벤트를 논리적으로 구성, 쉽게 찾고 수정 가능.
+- **단점**: 사소한 구조가 추가됨, 아주 작은 앱에는 과할 수 있음.
-### 옵션 3: 트리거되는 위치 가까이
-또 다른 접근법은 이벤트가 트리거되는 곳 근처에 이벤트를 등록하는 것입니다. 예를 들어, 컨트롤러나 경로 정의 내부에 배치하는 것입니다. 이 방법은 이벤트가 앱의 특정 부분에만 해당할 경우 잘 작동합니다.
+### 옵션 3: 발생시키는 위치 근처에
+또 다른 접근 방법은 이벤트를 발생시키는 위치, 즉 컨트롤러나 경로 정의 내에서 등록하는 것입니다. 이는 특정 앱의 한 부분에 이벤트가 독립적일 경우 잘 작동합니다.
```php
Flight::route('/signup', function () {
// 여기에서 이벤트 등록
Flight::onEvent('user.registered', function ($email) {
- echo "Welcome email sent to $email!";
+ echo "$email로 환영 이메일이 전송되었습니다!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Signed up!";
+ echo "가입되었습니다!";
});
```
-- **장점**: 연관된 코드를 함께 유지, 격리된 기능에 좋음.
-- **단점**: 이벤트 등록이 흩어질 수 있어 모든 이벤트를 한눈에 보기 어려워지고 조심하지 않으면 중복 등록 위험도 있음.
+- **장점**: 관련 코드를 함께 유지, 고립된 기능에 적합.
+- **단점**: 이벤트 등록이 흩어져 있어 모든 이벤트를 한 번에 보기 어려움; 조심하지 않으면 중복 등록의 위험.
-### Flight를 위한 모범 사례
-- **간단히 시작**: 작은 앱의 경우 `index.php`에 이벤트를 두세요. 빠르고 Flight의 최소화와 일치합니다.
-- **스마트하게 성장**: 앱이 확장될 때(예: 이벤트가 5-10개 이상), `app/config/events.php` 파일을 사용하세요. 이는 라우트를 조직하는 것처럼 자연스러운 단계이며, 복잡한 프레임워크 없이 코드를 깔끔하게 유지합니다.
-- **과도한 공학 피하기**: 앱이 커지지 않는 한 전체 "이벤트 관리자" 클래스나 디렉토리를 만들지 마세요—Flight는 단순함을 중시하므로 경량으로 유지하세요.
+### Flight의 모범 사례
+- **단순하게 시작하기**: 아주 작은 앱의 경우 `index.php`에 이벤트를 두세요. 빠르고 Flight의 단순성에 맞아떨어집니다.
+- **스마트하게 성장하기**: 앱이 확장됨에 따라(예: 5-10개 이상의 이벤트), `app/config/events.php` 파일을 사용하세요. 라우트를 정리하는 자연스러운 단계이며, 복잡한 프레임워크 없이 코드를 깔끔하게 유지할 수 있습니다.
+- **과도한 설계 피하기**: 앱이 거대해지지 않는 한 완전한 “이벤트 관리자” 클래스를 만들지 마십시오—Flight는 단순성에서 발전하는 것이므로 경량화된 것을 유지하세요.
-### 팁: 목적별 그룹화
-`events.php`에서 관련 이벤트(예: 모든 사용자 관련 이벤트)를 주석으로 그룹화하여 명확성을 유지하세요:
+### 팁: 목적별로 그룹화하기
+`events.php`에서 관련 이벤트를 그룹화(예: 모든 사용자 관련 이벤트를 함께 두기)하여 명확성을 위한 주석을 추가하세요:
```php
// app/config/events.php
// 사용자 이벤트
Flight::onEvent('user.login', function ($username) {
- error_log("$username logged in");
+ error_log("$username 로그인");
});
Flight::onEvent('user.registered', function ($email) {
- echo "Welcome to $email!";
+ echo "$email님을 환영합니다!";
});
// 페이지 이벤트
@@ -210,80 +210,86 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-이 구조는 잘 확장되고 초보자 친화적입니다.
+이러한 구조는 잘 확장되며 초보자 친화성을 유지합니다.
## 초보자를 위한 예제
-이벤트가 어떻게 작동하고 왜 도움이 되는지를 보여주기 위해 몇 가지 실제 시나리오를 살펴보겠습니다.
+이벤트가 어떻게 작동하는지, 그리고 왜 유용한지 보여주기 위해 몇 가지 실세계 시나리오를 살펴봅시다.
### 예제 1: 사용자 로그인 로깅
```php
// 1단계: 리스너 등록
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username logged in at $time");
+ error_log("$username 로그인 시간: $time");
});
// 2단계: 앱에서 트리거
Flight::route('/login', function () {
- $username = 'bob'; // 폼에서 오는 것처럼 가정
+ $username = 'bob'; // 이건 폼에서 오는 것이라고 가정합니다.
Flight::triggerEvent('user.login', $username);
- echo "Hi, $username!";
+ echo "안녕하세요, $username!";
});
```
-**유용한 이유**: 로그인 코드는 로깅에 대해 알 필요가 없습니다—그저 이벤트를 트리거할 뿐입니다. 나중에 더 많은 리스너(예: 환영 이메일 전송)를 추가할 수 있으며 라우트를 변경할 필요가 없습니다.
+**이것이 유용한 이유**: 로그인 코드는 로깅에 대해 알 필요가 없으며, 단지 이벤트를 트리거할 뿐입니다. 나중에 더 많은 리스너(예: 환영 이메일 보내기)를 추가해도 경로를 변경할 필요가 없습니다.
-### 예제 2: 신규 사용자 알림
+### 예제 2: 새로운 사용자 알림
```php
-// 신규 등록 리스너
+// 새 등록자를 위한 리스너
Flight::onEvent('user.registered', function ($email, $name) {
- // 이메일 전송 시뮬레이션
- echo "Email sent to $email: Welcome, $name!";
+ // 이메일 발송 시뮬레이션
+ echo "$email로 이메일 전송: $name님, 환영합니다!";
});
-// 누군가가 가입할 때 트리거
+// 누군가 가입할 때 트리거
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "Thanks for signing up!";
+ echo "가입 감사합니다!";
});
```
-**유용한 이유**: 가입 로직은 사용자를 생성하는 데 집중하고, 이벤트는 알림을 처리합니다. 나중에 더 많은 리스너(예: 가입 기록)를 추가할 수 있습니다.
+**이것이 유용한 이유**: 가입 논리는 사용자를 생성하는 것에 집중하며, 이벤트는 알림을 처리합니다. 나중에 더 많은 리스너(예: 가입 기록)를 추가할 수 있습니다.
### 예제 3: 캐시 지우기
```php
// 캐시 지우기 리스너
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // 적용 가능한 경우 세션 캐시 지우기
- echo "Cache cleared for page $pageId.";
+ unset($_SESSION['pages'][$pageId]); // 해당하는 경우 세션 캐시 지우기
+ echo "페이지 $pageId의 캐시가 지워졌습니다.";
});
// 페이지가 편집될 때 트리거
Flight::route('/edit-page/(@id)', function ($pageId) {
- // 페이지가 업데이트되었다고 가정
+ // 페이지가 수정되었다고 가정
Flight::triggerEvent('page.updated', $pageId);
- echo "Page $pageId updated.";
+ echo "페이지 $pageId가 업데이트되었습니다.";
});
```
-**유용한 이유**: 편집 코드는 캐시에 대해 알 필요가 없습니다—그저 업데이트를 신호 보낼 뿐입니다. 앱의 다른 부분은 필요에 따라 반응할 수 있습니다.
+**이것이 유용한 이유**: 편집 코드는 캐시에 대해 알 필요가 없으며, 단지 업데이트를 신호합니다. 앱의 다른 부분은 필요에 따라 반응할 수 있습니다.
## 모범 사례
-- **이벤트 명확하게 이름 짓기**: `'user.login'` 또는 `'page.updated'`와 같은 구체적인 이름을 사용하여 어떤 일을 하는지 명확하게 하세요.
-- **리스너를 간단하게 유지**: 느리거나 복잡한 작업을 리스너에 두지 마세요—앱을 빠르게 유지하세요.
-- **이벤트 테스트**: 수동으로 트리거하여 리스너가 예상대로 작동하는지 확인하세요.
-- **이벤트를 현명하게 사용하세요**: 이벤트는 디커플링에 훌륭하지만, 너무 많이 사용하면 코드를 이해하기 어려워질 수 있습니다—상황에 맞게 사용하세요.
+- **이벤트 이름을 명확하게**: `'user.login'` 또는 `'page.updated'`와 같은 구체적인 이름을 사용하세요. 무엇을 하는지 명확하게 하세요.
+- **리스너를 단순하게 유지**: 느리거나 복잡한 작업을 리스너에 두지 마세요—앱을 빠르게 유지하세요.
+- **이벤트를 테스트하세요**: 수동으로 트리거하여 리스너가 예상대로 작동하는지 확인하세요.
+- **이벤트를 현명하게 사용하세요**: 이벤트는 디커플링에 좋지만, 너무 많으면 코드를 이해하기 어려워질 수 있습니다—의미가 있는 경우에만 사용하세요.
-`Flight::onEvent()`과 `Flight::triggerEvent()`를 통해 Flight PHP의 이벤트 시스템은 유연한 애플리케이션 구축을 위한 단순하면서도 강력한 방법을 제공합니다. 애플리케이션의 서로 다른 부분이 이벤트를 통해 소통할 수 있도록 하여 코드를 조직적이고 재사용 가능하며 쉽게 확장할 수 있도록 합니다. 로그 작업 수행, 알림 전송 또는 업데이트 관리와 관계없이 이벤트는 논리를 얽히게 하지 않고 이를 처리하는 데 도움을 줍니다. 또한 이러한 메서드를 재정의 할 수 있는 능력을 통해 필요에 맞게 시스템을 조정할 수 있는 자유를 누릴 수 있습니다. 단일 이벤트로 작게 시작하고, 그것이 앱 구조를 어떻게 변형시키는지 지켜보세요!
+`Flight::onEvent()` 및 `Flight::triggerEvent()`를 통해 Flight PHP의 이벤트 시스템은 유연한 애플리케이션을 구축할 수 있는 간단하면서도 강력한 방법을 제공합니다. 애플리케이션의 서로 다른 부분이 이벤트를 통해 서로 대화할 수 있게 함으로써 코드를 조직적이고 재사용 가능하며 쉽게 확장할 수 있습니다. 행동을 로깅하고, 알림을 전송하거나, 업데이트를 관리하는 데 이벤트를 통해 논리를 얽히지 않게 유지할 수 있습니다. 게다가 이러한 메서드를 재정의할 수 있으므로 필요에 맞게 시스템을 사용자 정의할 수 있습니다. 단일 이벤트로 작게 시작하고 앱 구조가 어떻게 변할 수 있는지 지켜보세요!
## 내장 이벤트
-Flight PHP는 프레임워크의 생명 주기에서 특정 시점에 후킹할 수 있는 몇 가지 내장 이벤트를 제공합니다. 이러한 이벤트는 요청/응답 주기의 특정 지점에서 트리거되어 특정 작업이 발생할 때 사용자 정의 논리를 실행할 수 있게 해줍니다.
+Flight PHP는 프레임워크의 생명주기에서 후킹할 수 있는 몇 가지 내장 이벤트를 제공합니다. 이러한 이벤트는 요청/응답 주기의 특정 지점에서 트리거되어 특정 작업이 발생했을 때 사용자 정의 로직을 실행할 수 있도록 합니다.
### 내장 이벤트 목록
-- `flight.request.received`: 요청이 수신, 구문 분석 및 처리될 때 트리거됨.
-- `flight.route.middleware.before`: 이전 미들웨어가 실행된 후 트리거됨.
-- `flight.route.middleware.after`: 이후 미들웨어가 실행된 후 트리거됨.
-- `flight.route.executed`: 라우트가 실행되고 처리된 후 트리거됨.
-- `flight.response.sent`: 응답이 클라이언트에 전송된 후 트리거됨.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` 요청이 수신, 구문 분석 및 처리될 때 트리거됩니다.
+- **flight.error**: `function(Throwable $exception)` 요청 생명 주기 중 오류가 발생할 때 트리거됩니다.
+- **flight.redirect**: `function(string $url, int $status_code)` 리디렉션이 시작될 때 트리거됩니다.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` 특정 키에 대한 캐시가 확인될 때 트리거됩니다.
+- **flight.middleware.before**: `function(Route $route)` before 미들웨어가 실행된 후 트리거됩니다.
+- **flight.middleware.after**: `function(Route $route)` after 미들웨어가 실행된 후 트리거됩니다.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` 모든 미들웨어가 실행된 후 트리거됩니다.
+- **flight.route.matched**: `function(Route $route)` 경로가 일치했지만 아직 실행되지 않았을 때 트리거됩니다.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` 경로가 실행되고 처리된 후 트리거됩니다. `$executionTime`은 경로를 실행하는 데 걸린 시간입니다(컨트롤러 호출 등).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` 뷰가 렌더링된 후 트리거됩니다. `$executionTime`은 템플릿을 렌더링하는 데 걸린 시간입니다. **참고: `render` 메서드를 재정의하면 이 이벤트를 재트리거해야 합니다.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` 응답이 클라이언트에 전송된 후 트리거됩니다. `$executionTime`은 응답을 빌드하는 데 소요된 시간입니다.
\ No newline at end of file
diff --git a/content/v3/lv/awesome-plugins/apm.md b/content/v3/lv/awesome-plugins/apm.md
new file mode 100644
index 0000000..5d194f9
--- /dev/null
+++ b/content/v3/lv/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM Dokumentācija
+
+Laipni lūdzam FlightPHP APM — jūsu lietotnes personīgais veiktspējas treneris! Šis ceļvedis ir jūsu maršruts, lai iestatītu, lietotu un apgūtu Lietojumprogrammu veiktspējas uzraudzību (APM) ar FlightPHP. Neatkarīgi no tā, vai jūs meklējat lēnas pieprasījuma vai vienkārši vēlaties izpētīt latentuma grafikus, mēs jums palīdzēsim. Padarīsim jūsu lietotni ātrāku, jūsu lietotājus laimīgākus un jūsu atkļūdošanas sesijas vieglākas!
+
+## Kāpēc APM ir svarīgs
+
+Iedomājieties sekojošo: jūsu lietotne ir aizņemts restorāns. Bez veida, kā izsekot, cik ilgi pasūtījumi tiek veikti vai kur virtuvē ir kavēšanās, jūs minat, kādēļ klienti aiziet neapmierināti. APM ir jūsu sous-chef — tas uzrauga katru soli, sākot no ienākošiem pieprasījumiem līdz datu bāzes vaicājumiem, un noraksta visu, kas palēnina jūsu gaitu. Lēnas lapas zaudē lietotājus (pētījumi apgalvo, ka 53% pamet, ja vietne ielādējas ilgāk par 3 sekundēm!), un APM palīdz jums pamanīt šīs problēmas *pirms* tās jums sāp. Tas ir proaktīvs prāta miers — mazāk "kāpēc tas ir saplēsts?" mirkļu, vairāk "skaties, cik gludi tas darbojas!" uzvaras.
+
+## Instalācija
+
+Sāciet ar Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Jums būs nepieciešams:
+- **PHP 7.4+**: Nodrošina saderību ar LTS Linux distribūcijām, vienlaikus atbalstot mūsdienu PHP.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Vieglākais ietvars, ko mēs uzlabojam.
+
+## Sākums
+
+Šeit ir jūsu soli pa solim uz APM lielisko pasauli:
+
+### 1. Reģistrējiet APM
+
+Ievietojiet šo kodu savā `index.php` vai `services.php` failā, lai sāktu uzraudzību:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Kas notiek šeit?**
+- `LoggerFactory::create()` ņem jūsu konfigurāciju (vairāk par to drīz) un iestata žurnālu — SQLite pēc noklusējuma.
+- `Apm` ir zvaigzne — tā klausās Flight notikumus (pieprasījumus, maršrutus, kļūdas utt.) un apkopo metriku.
+- `bindEventsToFlightInstance($app)` sasaista to visu ar jūsu Flight lietotni.
+
+**Pro padoms: Paraugu ņemšana**
+Ja jūsu lietotne ir aizņemta, katra pieprasījuma žurnāļu saglabāšana var palielināt slodzi. Izmantojiet paraugu likmi (no 0.0 līdz 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Žurnāli 10% pieprasījumu
+```
+
+Tas uztur veiktspēju ātru, vienlaikus sniedzot jums kvalitatīvus datus.
+
+### 2. Konfigurējiet to
+
+Izpildiet šo, lai izveidotu savu `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Kas tas dara?**
+- Palaiž vedni, kas jautā, no kurienes nāk neapstrādātās metrikas (avots) un kur tiek nosūtīti apstrādātie dati (galamērķis).
+- Noklusējums ir SQLite — piemēram, `sqlite:/tmp/apm_metrics.sqlite` avotam, cits galamērķim.
+- Jums beidzot būs konfigurācija, kas izskatās tā:
+ ```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"
+ }
+ }
+ ```
+
+**Kāpēc divas vietas?**
+Neapstrādātās metrikas ātri sakrājas (domājiet par filtrētām žurnālu datnēm). Darbinieks tās apstrādā struktūrētā galamērķī priekš paneļa. Uztur lietas kārtībā!
+
+### 3. Apstrādājiet metrikas ar darbinieku
+
+Darbinieks pārveido neapstrādātās metrikas par paneļa gataviem datiem. Izpildiet 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 metrikām (noklusējuma partijas lielums) uz jūsu galamērķi.
+- Apstājas, kad ir pabeigta vai ja metrikas vairs nav.
+
+**Turpiniet darbināt to**
+Dzīvām lietotnēm jūs vēlēsieties nepārtrauktu apstrādi. Šeit ir jūsu iespējas:
+
+- **Daimon režīms**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Darbojas bezgalīgi, apstrādājot metrikas, kad tās ierodas. Lieliska priekš izstrādes vai maziem iestatījumiem.
+
+- **Crontab**:
+ Pievienojiet to savam crontab (`crontab -e`):
+ ```bash
+ * * * * * php /path/to/project/vendor/bin/runway apm:worker
+ ```
+ Izsist katru minūti — ideāli piemērota ražošanai.
+
+- **Tmux/Screen**:
+ Sāciet noņemamu sesiju:
+ ```bash
+ tmux new -s apm-worker
+ php vendor/bin/runway apm:worker --daemon
+ # Ctrl+B, tad D, lai noņemtu; `tmux attach -t apm-worker`, lai atjaunotu savienojumu
+ ```
+ Uztur to darbināmu pat tad, ja izrakstāties.
+
+- **Pielāgotas izmaiņas**:
+ ```bash
+ php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
+ ```
+ - `--batch_size 50`: Apstrādā 50 metrikas reizē.
+ - `--max_messages 1000`: Apstājas pēc 1000 metrikām.
+ - `--timeout 300`: Iziet pēc 5 minūtēm.
+
+**Kāpēc uztraukties?**
+Bez darbinieka jūsu panelis ir tukšs. Tas ir tilts starp neapstrādātajiem žurnāliem un rīcībai nepieciešamajiem ieskatiem.
+
+### 4. Palaižiet paneli
+
+Redziet jūsu lietotnes vitālos datus:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**Kas tas?**
+- Palaiž PHP serveri adresē `http://localhost:8001/apm/dashboard`.
+- Rāda pieprasījuma žurnālus, lēnus maršrutus, kļūdu likmes un daudz ko citu.
+
+**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`: Pieejami no jebkura IP (noderīgi attālinātai skatīšanai).
+- `--port 8080`: Izmantojiet citu portu, ja 8001 ir aizņemts.
+- `--php-path`: Norādiet uz PHP, ja tas nav jūsu PATH.
+
+Piekļūstiet URL savā pārlūkprogrammā un izpētiet!
+
+#### Ražošanas režīms
+
+Ražošanā jums, iespējams, nāksies izmēģināt dažādas tehnikas, lai panāktu paneļa darbību, jo ir iespējams, ka tur ir ugunsmūri un citi drošības pasākumi. Šeit ir dažas iespējas:
+
+- **Izmantojiet apgrieztos proksī**: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus uz paneli.
+- **SSH tunelis**: Ja varat SSH savienoties ar serveri, izmantojiet `ssh -L 8080:localhost:8001 youruser@yourserver`, lai tunelētu paneli jūsu lokālajā datorā.
+- **VPN**: Ja jūsu serveris ir aiz VPN, pieslēdzieties tam un piekļūstiet panelim tieši.
+- **Konfigurējiet ugunsmūri**: Atveriet 8001 portu savai IP vai servera tīklam (vai kādu citu portu, ko jūs esat iestatījis).
+- **Konfigurējiet Apache/Nginx**: Ja jums ir tīmekļa serveris priekš jūsu lietotnes, varat to konfigurēt uz domēna vai apakšdomēna. Ja to darāt, iestatiet dokumentu sakni uz `/path/to/your/project/vendor/flightphp/apm/dashboard`.
+
+#### Vēlaties citu paneli?
+
+Ja vēlaties, varat izveidot savu paneli! Pārlūkojiet `vendor/flightphp/apm/src/apm/presenter` direktoriju, lai iegūtu idejas par to, kā prezentēt datus savai panelei!
+
+## Paneļa funkcijas
+
+Panelis ir jūsu APM HQ — šeit ir tas, ko jūs redzēsiet:
+
+- **Pieprasījuma žurnāls**: Katrs pieprasījums ar laika zīmogu, URL, atbilžu kodu un kopējo laiku. Noklikšķiniet uz "Detālēs", lai redzētu starpprogrammas, vaicājumus un kļūdas.
+- **Lēnākie pieprasījumi**: Top 5 pieprasījumi, kas tērē laiku (piemēram, “/api/heavy” 2.5s).
+- **Lēnākie maršruti**: Top 5 maršruti pēc vidējā laika — lieliski, lai atklātu modeļus.
+- **Kļūdu likme**: Procentuālais pieprasījumu skaits, kas neizdodas (piemēram, 2.3% 500s).
+- **Latentuma percentīļi**: 95. (p95) un 99. (p99) atbilžu laiki — ziniet savus sliktākos gadījumus.
+- **Atbilžu koda diagramma**: Vizualizējiet 200s, 404s, 500s laika gaitā.
+- **Garie vaicājumi/Starpprogrammas**: Top 5 lēnākie datu bāzes zvani un starpprogrammas slāņi.
+- **Katrā hit/zaudējums**: Cik bieži jūsu kešatmiņa glābj dienu.
+
+**Papildinājumi**:
+- Filtrējiet pēc “pēdējās stundas”, “pēdējās dienas” vai “pēdējās nedēļas”.
+- Pārslēdziet tumšo režīmu nogurušām sesijām.
+
+**Piemērs**:
+Pieprasījums uz `/users` varētu parādīt:
+- Kopējais laiks: 150ms
+- Starpprogramma: `AuthMiddleware->handle` (50ms)
+- Vaicājums: `SELECT * FROM users` (80ms)
+- Kešatmiņa: Hit uz `user_list` (5ms)
+
+## Pievienojot pielāgotus notikumus
+
+Izsekojiet jebko — kā API zvanu vai maksājumu procesu:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Kur tas tiks parādīts?**
+Paneļa pieprasījumu detalizētās sadaļas zem "Pielāgoti notikumi" — izplatināms ar jauku JSON formātu.
+
+**Izmantošanas gadījums**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Tagad jūs redzēsiet, vai tas API palēnina jūsu lietotni!
+
+## Datu bāzes uzraudzība
+
+Izsekojiet PDO vaicājumus šādi:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Ko jūs iegūstat**:
+- Vaicājuma teksts (piemēram, `SELECT * FROM users WHERE id = ?`)
+- Izpildes laiks (piemēram, 0.015s)
+- Rindu skaits (piemēram, 42)
+
+**Uzziniet**:
+- **Pēc izvēles**: Izlaižiet to, ja nekas datu bāzes uzraudzība nav nepieciešama.
+- **Tikai PdoWrapper**: Galvenais PDO vēl nav piesaistīts — palieciet pievienoti!
+- **Veiktspējas brīdinājums**: Neapstrādāt katru vaicājumu datu bāzē ar lielu slodzi, var palēnināt lietas. Izmantojiet paraugu ņemšanu (`$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
+
+## Darbinieka opcijas
+
+Regulējiet darbinieku pēc saviem vēlmēm:
+
+- `--timeout 300`: Apstājas pēc 5 minūtēm — labi testēšanai.
+- `--max_messages 500`: Ierobežo līdz 500 metrikām — notur to finansiālajā limitā.
+- `--batch_size 200`: Apstrādā 200 reizē — līdzsvaro ātrumu un atmiņu.
+- `--daemon`: Nepārtraukti darbojas — ideāli piemērota tiešai 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.
+
+## Problēmu risināšana
+
+Iestiprinat? Izmēģiniet šos:
+
+- **Nē paneļa datu?**
+ - Vai darbinieks darbojas? Pārbaudiet `ps aux | grep apm:worker`.
+ - Vai konfigurācijas ceļi sakrīt? Pārliecinieties, ka `.runway-config.json` DSN norāda uz reālām datnēm.
+ - Rūpīgi palaižat `php vendor/bin/runway apm:worker`, lai apstrādātu gaidošās metrikas.
+
+- **Darbinieka kļūdas?**
+ - Ieskats jūsu SQLite datnēs (piemēram, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`).
+ - Pārbaudiet PHP žurnālus par steka pēdām.
+
+- **Paneļa nesāksies?**
+ - 8001 ports tiek izmantots? 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ēni?**
+ - Samaziniet paraugu likmi: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Samaziniet partijas lielumu: `--batch_size 20`.
\ 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 87739bf..c88226f 100644
--- a/content/v3/lv/awesome-plugins/awesome_plugins.md
+++ b/content/v3/lv/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
-# Lieliski spraudņi
+# Forši spraudņi
-Flight ir neticami paplašināms. Ir vairāki spraudņi, kurus var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietotnei. Daži ir oficiāli atbalstīti no Flight komandas, bet citi ir mikrolibratūras, lai palīdzētu jums sākt.
+Flight ir neticami paplašināms. Ir pieejams vairāk nekā daži spraudņi, kurus var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumam. Daži no tiem tiek oficiāli atbalstīti no Flight komandas, bet citi ir mikro/vieglas bibliotēkas, lai palīdzētu jums sākt.
-## API dokumentācija
+## API Dokumentācija
-API dokumentācija ir svarīga jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami daži rīki, kas palīdzēs jums izveidot API dokumentāciju jūsu Flight projektiem.
+API dokumentācija ir izšķiroša nozīme jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko gaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu jums ģenerēt API dokumentāciju jūsu Flight projektiem.
-- [FlightPHP OpenAPI ģenerators](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber raksts par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu savu API, izmantojot API pirmajā pieejā.
-- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, kas palīdz jums izveidot API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot, un to var pielāgot jūsu vajadzībām. Tas ir PHP bibliotēka, kas palīdz jums ģenerēt Swagger dokumentāciju.
+- [FlightPHP OpenAPI ģenerators](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 savu API, izmantojot API pirmās pieejas principu.
+- [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, lai atbilstu jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu jums ģenerēt Swagger dokumentāciju.
+
+## Lietojumprogrammu veiktspējas uzraudzība (APM)
+
+Lietojumprogrammu veiktspējas uzraudzība (APM) ir izšķiroša nozīme jebkurai lietojumprogrammai. Tā palīdz jums saprast, kā jūsu lietojumprogramma darbojas un kur ir šaurās vietas. Ir pieejami vairāki APM rīki, kurus var izmantot kopā ar Flight.
+- beta[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 šaurās vietas.
## Autentifikācija/Autorizācija
-Autentifikācija un autorizācija ir svarīgas jebkurai lietotnei, kurai ir nepieciešama kontrole, kas var piekļūt kam.
+Autentifikācija un autorizācija ir izšķiroša nozīme jebkurai lietojumprogrammai, kas prasa noteikt kontroli par to, kas var piekļūt kam.
-- oficiāli [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 lietotnei.
+- 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šatmiņa
-Kešatmiņa ir lielisks veids, kā paātrināt jūsu lietotni. Ir pieejami vairāki kešatmiņas bibliotēkas, ko var izmantot ar Flight.
+Kešatmiņa ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir pieejamas vairākas kešatmiņas bibliotēkas, kuras var izmantot kopā ar Flight.
-- oficiāli [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un patstāvīgs PHP kešatmiņas klase fails
+- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un patstāvīgs PHP iekšējo kešatmiņu klase
## CLI
-CLI lietotnes ir lielisks veids, kā mijiedarboties ar jūsu lietotni. Jūs varat tās izmantot, lai ģenerētu kontrolierus, parādītu visus maršrutus un vēl vairāk.
+CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat tās izmantot, lai ģenerētu kontrolierus, parādītu visas maršrutus un daudz ko citu.
-- oficiāli [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietotne, kas palīdz jums pārvaldīt jūsu Flight lietotnes.
+- 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īkdatnes
-Sīkfaili ir lielisks veids, kā glabāt nelielas datu daļiņas klienta pusē. Tos var izmantot, lai glabātu lietotāja preferences, lietojumprogrammas iestatījumus un vēl vairāk.
+Sīkdatnes ir lielisks veids, kā glabāt nelielus datus klienta pusē. Tos var izmantot, lai glabātu lietotāja preferences, lietojumprogrammas iestatījumus un daudz ko citu.
-- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Sīkfails ir PHP bibliotēka, kas piedāvā vienkāršu un efektīvu veidu, kā pārvaldīt sīkfailus.
+- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Sīkdatne ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkdatnes.
## Kļūdu novēršana
-Kļūdu novēršana ir svarīga, kad jūs izstrādājat savā vietējā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu novēršanas pieredzi.
+Kļūdu novēršana ir izšķiroša, kad jūs attīstāt savā vietējā vidē. Ir pieejami daži spraudņi, kas var uzlabot jūsu kļūdu novēršanas pieredzi.
-- [tracy/tracy](/awesome-plugins/tracy) - Tas ir pilnībā funkcionalizēts kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums novērst kļūdas jūsu lietotnē. To ir arī ļoti viegli paplašināt un pievienot savus paneļus.
-- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Šis spraudnis, kas tiek izmantots kopā ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu novēršanu īpaši Flight projektiem.
+- [tracy/tracy](/awesome-plugins/tracy) - Tas ir pilna funkcionalitātes kļūdu apstrādātājs, ko var izmantot kopā ar Flight. Tam ir daudz paneļu, kas var palīdzēt jums novērst kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot [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 novēršanu tieši Flight projektiem.
## Datu bāzes
-Datu bāzes ir galvenā jebkurai lietotnei. Tā ir veids, kā jūs glabājat un iegūstat datus. Dažas datu bāzu bibliotēkas ir vienkārši apvalki, lai rakstītu vaicājumus, un dažas ir pilnīgas ORM.
+Datu bāzes ir pamatā lielākajām lietojumprogrammām. Tā ir vieta, kur jūs glabājat un iegūstat datus. Dažas datu bāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnīgi izstrādātas ORM.
-- oficiāli [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Tas ir vienkāršs apvalks, kas palīdz vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM.
-- oficiāli [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Karte. Lieliska maza bibliotēka, lai viegli iegūtu un glabātu datus jūsu datu bāzē.
-- [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, kas ļauj sekot līdzi visām izmaiņām datu bāzē jūsu projektam.
+- oficiāls [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Oficiālais Flight PDO Wrapper, kas ir daļa no pamatnes. Tas ir vienkāršs apvalks, lai vienkāršotu vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM.
+- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālais Flight ActiveRecord ORM/Mapper. Lieliska mazā bibliotēka, lai viegli iegūtu un glabātu datus jūsu datu bāzē.
+- [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, lai sekotu visām datu bāzes izmaiņām jūsu projektam.
## Šifrēšana
-Šifrēšana ir svarīga jebkurai lietotnei, kas glabā sensitīvus datus. Datu šifrēšana un atšifrēšana nav pārāk grūta, taču pareiza šifrēšanas atslēgas glabāš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). Svarīgākais ir nekad neglabāt savu šifrēšanas atslēgu publiskajā direktorijā vai neieguldīt to savā kodu krātuvē.
+Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas glabā sensitīvus datus. Datu šifrēšana un atšifrēšana nav grūta, bet pareiza šifrēšanas atslēgas glabāš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). Visizšķirošākais ir nekad neglabāt jūsu šifrēšanas atslēgu publiskajā direktorijā vai to nodot savā koda krātuvē.
-- [defuse/php-encryption](/awesome-plugins/php-encryption) - Tā ir bibliotēka, ko var izmantot datu šifrēšanai un atšifrēšanai. Sākt izmantot ir diezgan vienkārši, lai sāktu šifrēt un atšifrēt datus.
+- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot datu šifrēšanai un atšifrēšanai. Sākt šifrēšanu un atšifrēšanu ir salīdzinoši vienkārši.
-## Uzdevumu rinda
+## Darbu rinda
-Uzdevumu rindas ir ļoti noderīgas, lai asinkroni apstrādātu uzdevumus. Tas var būt e-pastu sūtīšana, attēlu apstrāde vai viss, kas nav jāveic tiešsaistē.
+Darbu rindas ir ļoti noderīgas, lai asinkroni apstrādātu uzdevumus. Tas var būt epastu sūtīšana, attēlu apstrāde vai jebkas, kas nav jāveic reāllaikā.
-- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Vienkārša uzdevumu rinda ir bibliotēka, ko var izmantot, lai apstrādātu uzdevumus asinkroni. 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 asinkroni apstrādātu darbus. To var izmantot kopā ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL.
## Sesija
-Sesijas nav īpaši noderīgas API, bet, veidojot tīmekļa lietotni, sesijas var būt būtiskas stāvokļa un pieteikšanās informācijas saglabāš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ēšanā.
-- oficiāli [flightphp/session](/awesome-plugins/session) - Oficiālā Flight sesiju bibliotēka. Šī ir vienkārša sesiju bibliotēka, ko var izmantot, lai glabātu un iegūtu sesijas datus. Tā izmanto PHP iebūvēto sesiju apstrādi.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP sesiju pārvaldnieks (nebloķējošs, flash, segments, sesijas šifrēšana). Izmanto PHP open_ssl, lai opcionalizētu sesijas datu šifrēšanu/atšifrēšanu.
+- oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight sesiju bibliotēka. Šī ir vienkārša sesiju bibliotēka, ko var izmantot, lai glabātu un iegūtu sesiju datus. Tā izmanto PHP iebūvēto sesiju apstrādi.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP sesiju pārvaldnieks (nebloķējošs, mirkļi, segments, sesijas šifrēšana). Izmanto PHP open_ssl, lai optional šifrētu/atšifrētu sesijas datus.
-## Veidnes
+## Šablonēšana
-Veidnes ir pamatā jebkurai tīmekļa lietotnei ar UI. Ir pieejami vairāki veidņu dzinēji, ko var izmantot ar Flight.
+Šablonēšana ir pamatā jebkurai tīmekļa lietojumprogrammai ar UI. Ir pieejami vairāki šablonēšanas dzinēji, kurus var izmantot kopā ar Flight.
-- novecojis [flightphp/core View](/learn#views) - Tā ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. To nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā dažas lapas.
-- [latte/latte](/awesome-plugins/latte) - Latte ir pilnībā funkcionāls veidņu dzinējs, ko ir ļoti viegli izmantot un kas atgādina PHP sintaksi vairāk nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas.
+- atkalizmantots [flightphp/core View](/learn#views) - Tas ir ļoti vienkāršs šablonēšanas dzinējs, kas ir daļa no pamatnes. To nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā dažas lapas.
+- [latte/latte](/awesome-plugins/latte) - Latte ir pilnīga funkcionalitātes šablonēšanas dzinēja, 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.
-## Ieguldījumi
+## Piedalīšanās
-Vai jums ir spraudnis, ko vēlētos dalīties? Iesniedziet pieprasījumu par pievienošanu tā sarakstam!
\ No newline at end of file
+Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet vilkšanas pieprasījumu, lai to pievienotu sarakstam!
\ No newline at end of file
diff --git a/content/v3/lv/awesome-plugins/tracy_extensions.md b/content/v3/lv/awesome-plugins/tracy_extensions.md
index 20cc359..5a070d3 100644
--- a/content/v3/lv/awesome-plugins/tracy_extensions.md
+++ b/content/v3/lv/awesome-plugins/tracy_extensions.md
@@ -1,14 +1,14 @@
-# Tracy Flight Panel Extensions
+Tracy Flight Panel Paplašinājumi
=====
-Tas ir komplekts paplašinājumu, kas padara darbu ar Flight nedaudz bagātāku.
+Tas ir paplašinājumu kopums, lai padarītu darbu ar Flight nedaudz bagātāku.
- Flight - Analizēt visus Flight mainīgos.
-- Database - Analizēt visus pieprasījumus, kas ir izpildīti lapā (ja pareizi inicializējat datu bāzes savienojumu)
-- Request - Analizēt visus `$_SERVER` mainīgos un izpētīt visus globālos dati (`$_GET`, `$_POST`, `$_FILES`)
-- Session - Analizēt visus `$_SESSION` mainīgos, ja sesijas ir aktīvas.
+- Datubāze - Analizēt visus vaicājumus, kas tika izpildīti lapā (ja pareizi inicializējat datubāzes savienojumu)
+- Pieprasījums - Analizēt visus `$_SERVER` mainīgos un pārbaudīt visus globālos datus (`$_GET`, `$_POST`, `$_FILES`)
+- Sesija - Analizēt visus `$_SESSION` mainīgos, ja sesijas ir aktīvas.
-Šī ir panelis
+Tas ir Panelis

@@ -18,15 +18,15 @@ Un katrs panelis rāda ļoti noderīgu informāciju par jūsu lietojumprogrammu!


-Noklikšķiniet [šeit](https://github.com/flightphp/tracy-extensions), lai skatītu kodu.
+Noklikšķiniet [šeit](https://github.com/flightphp/tracy-extensions), lai apskatītu kodu.
-## Instalācija
+Uzstādīšana
-------
-Izpildiet `composer require flightphp/tracy-extensions --dev` un jūs esat gatavs!
+Izpildiet `composer require flightphp/tracy-extensions --dev` un jūs esat ceļā!
Konfigurācija
-------
-Lai sāktu izmantot šo, jums ir nepieciešama ļoti maza konfigurācija. Jums būs jāinicializē Tracy atkļūdošana pirms šī sākuma [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Ir ļoti maz konfigurācijas, ko jūs vajadzētu veikt, lai sāktu darbu. Jums būs jāinicializē Tracy tīklā, pirms to izmantosiet [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // Tas jābūt viltus, vai arī Tracy faktiski nevar atveidot :(
+ // Tam jābūt nepatiesam, vai Tracy patiešām nevar attēlot :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
-// maršruti un citi lielumi...
+// maršruti un citas lietas...
Flight::start();
```
### Latte
-Ja jums ir Latte instalēts jūsu projektā, jūs varat izmantot Latte paneli, lai analizētu savus veidnes. Jūs varat nodot Latte instanci `TracyExtensionLoader` konstruktorā ar atslēgu `latte` otro parametru.
+Ja jums ir Latte uzstādīts jūsu projektā, jūs varat izmantot Latte paneli, lai analizētu savus veidnes. Jūs varat nodot Latte instanci `TracyExtensionLoader` konstruktoram ar `latte` atslēgu otrajā parametru.
```php
@@ -101,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // šeit jūs pievienojat Latte Paneļu Tracy
+ // šeit jūs pievienojat Latte paneli Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // Tas jābūt viltus, vai arī Tracy faktiski nevar atveidot :(
+ // Tam jābūt nepatiesam, vai Tracy patiešām nevar attēlot :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/lv/learn/events.md b/content/v3/lv/learn/events.md
index edade88..10d82b0 100644
--- a/content/v3/lv/learn/events.md
+++ b/content/v3/lv/learn/events.md
@@ -1,41 +1,41 @@
-# Notikumu sistēma Flight PHP (v3.15.0+)
+# Pasākumu sistēma Flight PHP (v3.15.0+)
-Flight PHP ievieš vieglu un intuitīvu notikumu sistēmu, kas ļauj reģistrēt un izsaukt pielāgotus notikumus jūsu lietojumprogrammi. Pievienojot `Flight::onEvent()` un `Flight::triggerEvent()`, tagad varat pieslēgties galvenajām jūsu lietojumprogrammas dzīves cikla brīžiem vai definēt savus notikumus, lai padarītu jūsu kodu modulārāku un izplešamu. Šīs metodes ir daļa no Flight **kartējamo metožu**, kas nozīmē, ka jūs varat pārrakstīt to uzvedību, lai atbilstu jūsu vajadzībām.
+Flight PHP ievieš vieglu un intuitīvu pasākumu sistēmu, kas ļauj reģistrēt un izsistīt pielāgotus pasākumus jūsu lietojumprogrammā. Pievienojot `Flight::onEvent()` un `Flight::triggerEvent()`, jūs tagad varat pieslēgties jūsu lietojumprogrammas dzīves cikla nozīmīgajiem brīžiem vai definēt savus pasākumus, lai padarītu jūsu kodu modulāru un paplašināmu. Šīs metodes ir daļa no Flight **kartējamajām metodēm**, tas nozīmē, ka jūs varat pārdefinēt to uzvedību, lai pielāgotu to savām vajadzībām.
-Šis ceļvedis aptver visu, kas jums jāzina, lai sāktu strādāt ar notikumiem, tostarp to, kāpēc tie ir vērtīgi, kā tos izmantot un praktiskus piemērus, lai palīdzētu iesācējiem saprast to jaudu.
+Šis ceļvedis aptver visu, kas jums jāzina, lai uzsāktu darbu ar pasākumiem, ieskaitot, kāpēc tie ir vērtīgi, kā tos izmantot un praktiskus piemērus, lai palīdzētu iesācējiem saprast to potenciālu.
-## Kāpēc izmantot notikumus?
+## Kāpēc izmantot pasākumus?
-Notikumi ļauj jums atdalīt dažādas jūsu lietojumprogrammas daļas, lai tās nenovērstu pārāk stipri viena no otras. Šī atdalīšana—bieži saukta par **dekopēšanu**—padara jūsu kodu vieglāk atjaunināmu, paplašināmu vai atkļūdējamu. Tā vietā, lai rakstītu visu vienā lielā gabalā, jūs varat sadalīt loģiku mazākās, neatkarīgās daļās, kas reaģē uz specifiskām rīcībām (notikumiem).
+Pasākumi ļauj jums atdalīt dažādas jūsu lietojumprogrammas daļas, lai tās stipri neatkarētu viena no otras. Šī atdalīšana—bieži saukta par **atslēgšanu**—padara jūsu kodu vieglāk atjauninātu, paplašinātu vai labotu. Tā vietā, lai uzrakstītu visu vienā lielā blokā, jūs varat sadalīt savu loģiku mazākos, neatkarīgos gabalos, kas reaģē uz konkrētām darbībām (pasākumiem).
-Iedomājieties, ka jūs veidojat emuāra lietojumprogrammu:
-- Kad lietotājs publicē komentāru, jūs varētu vēlēties:
- - Saglabāt komentāru datubāzē.
- - Nosūtīt e-pastu emuāra īpašniekam.
- - Pierakstīt rīcību drošībai.
+Iedomājieties, ka jūs veidojat bloga lietojumprogrammu:
+- Kad lietotājs ievieto komentāru, jūs varat vēlēties:
+ - Saglabāt komentāru datu bāzē.
+ - Nosūtīt e-pastu bloga īpašniekam.
+ - Reģistrēt darbību drošībai.
-Bez notikumiem jūs salieksiet visu šo vienā funkcijā. Ar notikumiem jūs varat to sadalīt: viena daļa saglabā komentāru, otra izsauc notikumu, piemēram, `'comment.posted'`, un atsevišķie klausītāji apstrādā e-pastu un ierakstīšanu. Tas padara jūsu kodu tīrāku un ļauj pievienot vai noņemt funkcijas (piemēram, paziņojumus) bez kodola loģikas skarsanas.
+Bez pasākumiem jūs visu šo iepazīsiet vienā funkcijā. Ar pasākumiem jūs varat to sadalīt: viena daļa saglabā komentāru, otra izsist pasākumu, piemēram, `'comment.posted'`, un atsevišķi klausītāji apstrādā e-pastu un reģistrēšanu. Tas saglabā jūsu kodu tīrāku un ļauj jums pievienot vai noņemt funkcijas (piemēram, paziņojumus), nepieskaroties pamatloģikai.
-### Biežākās izmantošanas iespējas
-- **Ierakstīšana**: Pierakstiet rīcības, piemēram, pieteikšanos vai kļūdas, bez jūsu galvenā koda sajaukšanas.
-- **Paziņojumi**: Nosūtiet e-pastus vai brīdinājumus, kad notiek kaut kas.
-- **Atjauninājumi**: Atsvaidziniet kešatmiņas vai paziņojiet citām sistēmām par izmaiņām.
+### Bieži lietojumi
+- **Reģistrēšana**: Ierakstīt darbības, piemēram, pieteikšanos vai kļūdas, nepiesārņojot jūsu galveno kodu.
+- **Paziņojumi**: Nosūtīt e-pastus vai brīdinājumus, kad notiek kaut kas.
+- **Atjauninājumi**: Atsvaidzināt kešatmiņas vai paziņot citām sistēmām par izmaiņām.
-## Notikumu klausītāju reģistrācija
+## Pasākumu klausītāju reģistrēšana
-Lai klausītos notikumu, izmantojiet `Flight::onEvent()`. Šī metode ļauj jums definēt, kas notiks, kad notikums notiks.
+Lai klausītos uz pasākumu, izmantojiet `Flight::onEvent()`. Šī metode ļauj jums definēt, kas notiks, kad pasākums notiek.
### Sintakse
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Nosaukums jūsu notikumam (piemēram, `'user.login'`).
-- `$callback`: Funkcija, kas tiks izpildīta, kad notikums tiks izsaukts.
+- `$event`: Nosaukums jūsu pasākumam (piemēram, `'user.login'`).
+- `$callback`: Funkcija, kas jāizpilda, kad pasākums tiek izsists.
### Kā tas darbojas
-Jūs "abonējat" notikumu, sakot Flight, ko darīt, kad tas notiek. Atzīme var pieņemt argumentus, ko nodrošina notikuma izsaukums.
+Jūs "pierakstāties" uz pasākumu, sakot Flight, ko darīt, kad tas notiek. Atgriezeniskā funkcija var pieņemt argumentus, kas tiek nodoti no pasākuma izsistšanas.
-Flight notikumu sistēma ir sinhrona, kas nozīmē, ka katrs notikumu klausītājs tiek izpildīts secībā, viens pēc otra. Kad jūs izsaucat notikumu, visi reģistrētie klausītāji šim notikumam tiks izpildīti līdz beigām, pirms jūsu kods turpinās. Tas ir svarīgi saprast, jo tas atšķiras no asinhronām notikumu sistēmām, kur klausītāji var darboties paralēli vai vēlā laikā.
+Flight pasākumu sistēma ir sinhrona, kas nozīmē, ka katrs pasākumu klausītājs tiek izpildīts secīgi, viens pēc otra. Kad jūs izsitat pasākumu, visi reģistrētie klausītāji šim pasākumam tiks izpildīti līdz beigām, pirms jūsu kods turpinās. Tas ir svarīgi saprast, jo tas atšķiras no asinkronajiem pasākumu sistēmām, kur klausītāji var darboties paralēli vai vēlāk.
### Vienkāršs piemērs
```php
@@ -43,47 +43,47 @@ Flight::onEvent('user.login', function ($username) {
echo "Laipni lūdzam atpakaļ, $username!";
});
```
-Šeit, kad notiek notikums `'user.login'`, tas sveicina lietotāju pa vārdam.
+Šeit, kad pasākums `'user.login'` tiek izsists, tas sveicinās lietotāju pēc vārda.
### Galvenie punkti
-- Jūs varat pievienot vairākus klausītājus vienam un tam pašam notikumam—tie izpildīsies reģistrācijas secībā.
-- Atzīme var būt funkcija, anonīma funkcija vai metode no klases.
+- Jūs varat pievienot vairākus klausītājus vienam un tam pašam pasākumam—tie darbosies tajā secībā, kādā jūs tos reģistrējāt.
+- Atgriezeniskā funkcija var būt funkcija, anonīma funkcija vai metode no klases.
-## Notikumu izsaukšana
+## Pasākumu izsistīšana
-Lai notikums notiktu, izmantojiet `Flight::triggerEvent()`. Tas saka Flight, lai izpildītu visus klausītājus, kuri ir reģistrēti šim notikumam, nododot visas datus, ko jūs sniedzat.
+Lai izsistītu pasākumu, izmantojiet `Flight::triggerEvent()`. Tas norāda Flight, lai izpildītu visus klausītājus, kas reģistrēti šim pasākumam, nododot jebkādus datus, ko sniedzat.
### Sintakse
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: Notikuma nosaukums, kuru izsaucat (jāatbilst reģistrētajam notikumam).
-- `...$args`: Opcionāli argumenti, ko nosūtīt klausītājiem (var būt jebkurš argumentu skaits).
+- `$event`: Pasākuma nosaukums, ko jūs izsitat (jāatbilst reģistrētam pasākumam).
+- `...$args`: Papildus argumenti, kurus nosūtīt klausītājiem (var būt jebkura skaita argumenti).
### Vienkāršs piemērs
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Tas izsauc notikumu `'user.login'` un nosūta `'alice'` klausītājam, ko mēs iepriekš definējām, kas izvadīs: `Laipni lūdzam atpakaļ, alice!`.
+Tas izsist pasākumu `'user.login'` un nosūta `'alice'` klausītājam, ko mēs definējām iepriekš, kas izvadīs: `Laipni lūdzam atpakaļ, alice!`.
### Galvenie punkti
-- Ja nav reģistrētu klausītāju, nekas nenotiek—jūsu lietojumprogramma nesabrūk.
-- Izmantojiet izklāšanas operatoru (`...`), lai elastīgi nodotu vairākus argumentus.
+- Ja nav reģistrētu klausītāju, nekas nenotiek—jūsu lietojumprogramma nesabruks.
+- Izmantojiet izplatīšanas operatoru (`...`), lai elastīgi nodotu vairākus argumentus.
-### Notikumu klausītāju reģistrācija
+### Pasākumu klausītāju reģistrēšana
...
-**Nākamo klausītāju apstādināšana**:
-Ja klausītājs atgriež `false`, nekādi papildu klausītāji šim notikumam netiks izpildīti. Tas ļauj jums pārtraukt notikumu ķēdi, pamatojoties uz specifiskām nosacījumiem. Atcerieties, ka klausītāju secība ir svarīga, jo pirmais, kurš atgriež `false`, apstās pārējos no izpildes.
+**Turbīnā turpmāks klausītājs**:
+Ja klausītājs atgriež `false`, nekādi papildu klausītāji šim pasākumam netiks izpildīti. Tas ļauj jums apturēt pasākumu ķēdi, pamatojoties uz noteiktām nosacījumiem. Atcerieties, ka klausītāju secība ir svarīga, jo pirmais, kas atgriež `false`, apturēs pārējo izpildi.
**Piemērs**:
```php
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // Apstājas sekojošo klausītāju izpilde
+ return false; // Aptur nākamos klausītājus
}
});
Flight::onEvent('user.login', function ($username) {
@@ -91,60 +91,60 @@ Flight::onEvent('user.login', function ($username) {
});
```
-## Notikumu metožu pārrakstīšana
+## Pasākumu metožu pārdefinēšana
-`Flight::onEvent()` un `Flight::triggerEvent()` ir pieejami [paplašināšanai](/learn/extending), kas nozīmē, ka jūs varat pārrakstīt, kā tās darbojas. Tas ir lieliski piemērots progresīviem lietotājiem, kuri vēlas pielāgot notikumu sistēmu, piemēram, pievienojot ierakstīšanu vai mainot veidu, kā notikumi tiek izsaukti.
+`Flight::onEvent()` un `Flight::triggerEvent()` ir pieejami, lai tiktu [paplašināti](/learn/extending), tas nozīmē, ka jūs varat pārdefinēt to darbību. Tas ir lieliski piemērots pieredzējušiem lietotājiem, kuri vēlas pielāgot pasākumu sistēmu, piemēram, pievienojot reģistrēšanu vai mainot, kā pasākumi tiek izsisti.
-### Piemērs: Pielāgošana `onEvent`
+### Piemērs: Pielāgojot `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // Pieraksta katru notikumu reģistrāciju
- error_log("Jauns notikumu klausītājs pievienots: $event");
- // Izsaukt noklusējuma uzvedību (pieņemot, ka ir iekšēja notikumu sistēma)
+ // Reģistrēt katru pasākumu reģistrāciju
+ error_log("Jauns pasākumu klausītājs pievienots: $event");
+ // Izsist standarta uzvedību (pieņemot, ka ir iekšēja pasākumu sistēma)
Flight::_onEvent($event, $callback);
});
```
-Tagad, katru reizi, kad jūs reģistrējat notikumu, tas tiek pierakstīts pirms turpināšanas.
+Tagad, katru reizi, kad jūs reģistrējat pasākumu, tas tiek ierakstīts pirms turpināšanas.
-### Kāpēc pārrakstīt?
+### Kāpēc pārdefinēt?
- Pievienot atkļūdošanu vai uzraudzību.
-- Ierobežot notikumus noteiktās vidēs (piemēram, atslēgt testēšanas laikā).
-- Integrēt ar citu notikumu bibliotēku.
+- Ierobežot pasākumus noteiktās vidēs (piemēram, izslēgt testēšanas laikā).
+- Integrēt ar citu pasākumu bibliotēku.
-## Kur ievietot savus notikumus
+## Kur ievietot savus pasākumus
-Kā iesācējam, jūs varētu brīnīties: *kur reģistrēt visus šos notikumus manā lietojumprogrammā?* Flight vienkāršība nozīmē, ka nav stingru noteikumu—jūs varat tos ievietot tur, kur tas ir jēgpilni jūsu projektam. Tomēr, saglabājot tos organizētus, jūs palīdzat uzturēt savu kodu, kad jūsu lietojumprogramma aug. Šeit ir daži praktiski varianti un labākās prakses, kas pielāgotas Flight vieglajai dabai:
+Kā iesācējs, jūs varat jautāt: *kur reģistrēt visus šos pasākumus savā lietojumprogrammā?* Flight vienkāršība nozīmē, ka nav stingru noteikumu—jūs varat tos ievietot kur vien tas ir piemērots jūsu projektam. Tomēr, saglabājot tos organizētus, jūs palīdzat uzturēt savu kodu, kad jūsu lietojumprogramma aug. Šeit ir daži praktiski varianti un labākās prakses, pielāgotas Flight vieglajai būtībai:
### Variants 1: Jūsu galvenajā `index.php`
-Mazām lietojumprogrammām vai ātrām prototipiem jūs varat reģistrēt notikumus tieši savā `index.php` failā blakus savām maršrutām. Tas viss saglabā vienā vietā, kas ir labi tad, kad vienkāršība ir jūsu prioritāte.
+Nelielām lietojumprogrammām vai ātriem prototipiem jūs varat reģistrēt pasākumus tieši savā `index.php` failā kopā ar maršrutiem. Tas viss saglabā vienā vietā, kas ir labi, kad vienkāršība ir jūsu galvenā prioritāte.
```php
require 'vendor/autoload.php';
-// Reģistrēt notikumus
+// Reģistrēt pasākumus
Flight::onEvent('user.login', function ($username) {
- error_log("$username piesakās plkst. " . date('Y-m-d H:i:s'));
+ error_log("$username pieteicies " . date('Y-m-d H:i:s'));
});
// Definēt maršrutus
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Pieslēdzies!";
+ echo "Pieteicies!";
});
Flight::start();
```
- **Priekšrocības**: Vienkārši, nav papildu failu, lieliski maziem projektiem.
-- **Trūkumi**: Var kļūt nekārtīgi, kamēr jūsu lietojumprogramma aug ar vairāk notikumiem un maršrutiem.
+- **Trūkumi**: Var kļūt haotiski, kad jūsu lietojumprogramma aug ar vairāk pasākumiem un maršrutiem.
### Variants 2: Atsevišķs `events.php` fails
-Nedaudz lielākai lietojumprogrammai apsveriet iespēju pārvietot notikumu reģistrāciju uz veltītu failu, piemēram, `app/config/events.php`. Iekļaujiet šo failu savā `index.php` pirms maršrutiem. Tas atgādina par to, kā maršruti bieži tiek organizēti `app/config/routes.php` Flight projektos.
+Nedaudz lielākai lietojumprogrammai apsveriet iespēju pārvietot pasākumu reģistrācijas uz veltītu failu, piemēram, `app/config/events.php`. Iekļaujiet šo failu savā `index.php` pirms maršrutiem. Tas atdarina, kā maršruti bieži tiek organizēti `app/config/routes.php` Flight projektos.
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username piesakās plkst. " . date('Y-m-d H:i:s'));
+ error_log("$username pieteicies " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
@@ -160,130 +160,136 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Pieslēdzies!";
+ echo "Pieteicies!";
});
Flight::start();
```
-- **Priekšrocības**: Saglabā `index.php` koncentrētas uz maršrutiem, organizē notikumus loģiski, viegli atrast un rediģēt.
-- **Trūkumi**: Pievieno nelielu struktūru, kas var šķist pārspīlēta ļoti mazām lietojumprogrammām.
+- **Priekšrocības**: Saglabā `index.php` koncentrēts uz maršrutiem, organizē pasākumus loģiski, viegli atrast un rediģēt.
+- **Trūkumi**: Pievieno nedaudz struktūras, kas var šķist pārspīlēti ļoti maziem gabaliem.
-### Variants 3: Tuvojieties vietai, kur tie tiek izsaukti
-Cits pieejas veids ir reģistrēt notikumus tuvu tam, kur tie tiek izsaukti, piemēram, kontroliera vai maršruta definīcijā. Tas labi darbojas, ja notikums ir specifisks vienai jūsu lietojumprogrammas daļai.
+### Variants 3: Tuvojoties, kur viņi tiek izsisti
+Vēl viens pieejas veids ir reģistrēt pasākumus tuvu vietai, kur tie tiek izsisti, piemēram, iekšā kontrolierī vai maršruta definīcijā. Tas labi darbojas, ja pasākums ir specifisks vienai jūsu lietojumprogrammas daļai.
```php
Flight::route('/signup', function () {
- // Reģistrēt notikumu šeit
+ // Reģistrēt pasākumu šeit
Flight::onEvent('user.registered', function ($email) {
- echo "Laipni lūdzam e-pastā $email!";
+ echo "Laipni lūdzam e-pastā nosūtītā $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Reģistrējies!";
+ echo "Pieteicies!";
});
```
- **Priekšrocības**: Saglabā saistīto kodu kopā, labi izolētām funkcijām.
-- **Trūkumi**: Izkliedē notikumu reģistrācijas, padarot grūtāk redzēt visus notikumus uzreiz; risks dublēt reģistrācijas, ja neesat uzmanīgs.
+- **Trūkumi**: Izkliedē pasākumu reģistrācijas, apgrūtina visu pasākumu vienlaicīgu apskati; riski dubultiem reģistrācijām, ja neesat uzmanīgs.
### Labākā prakse Flight
-- **Sākt vienkārši**: Īsām lietojumprogrammām ievietojiet notikumus `index.php`. Tas ir ātri un atbilst Flight minimālismam.
-- **Izaugsme gudri**: Kad jūsu lietojumprogramma paplašinās (piemēram, vairāk nekā 5-10 notikumu), izmantojiet `app/config/events.php` failu. Tas ir dabisks solis uz augšu, kā organizēt maršrutus, un uztur jūsu kodu tīru bez sarežģītu ietvaru pievienošanas.
-- **Izvairieties no pārmērīgas inženierijas**: Nelietojiet radīt pilnīgu "notikumu pārvaldnieka" klasi vai direktoriju, ja vien jūsu lietojumprogramma kļūst liela—Flight uzplaukst uz vienkāršības, tāpēc saglabājiet to vieglu.
+- **Sāciet ar vienkāršu**: Ļoti maziem gabaliem ievietojiet pasākumus `index.php`. Tas ir ātri un atbilst Flight minimālismam.
+- **Audziniet gudri**: Kad jūsu lietojumprogramma paplašinās (piemēram, vairāk nekā 5-10 pasākumi), izmantojiet `app/config/events.php` failu. Tas ir dabisks solis uz augšu, piemēram, maršrutu organizēšana, un saglabā jūsu kodu kārtīgu bez sarežģītu sistēmu pievienošanas.
+- **Izvairieties no pārmērīgas struktūras**: Nepievienojiet pilnvērtīgu "pasākumu pārvaldīšanas" klasi vai direktoriju, ja jūsu lietojumprogramma kļūst milzīga—Flight uzplaukst vienkāršībā, tādēļ saglabājiet to vieglu.
-### Ieteikums: Grupējiet pēc mērķa
-Failā `events.php` grupējiet saistītus notikumus (piemēram, visus lietotājiem saistītos notikumus) ar komentāriem skaidrībai:
+### Padoms: Grupējiet pēc mērķa
+Failā `events.php` grupējiet saistītus pasākumus (piemēram, visus lietotāju saistītos pasākumus kopā) ar komentāriem skaidrībai:
```php
// app/config/events.php
-// Lietotāju notikumi
+// Lietotāju pasākumi
Flight::onEvent('user.login', function ($username) {
- error_log("$username piesakās");
+ error_log("$username pieteicies");
});
Flight::onEvent('user.registered', function ($email) {
- echo "Laipni lūdzam $email!";
+ echo "Laipni lūdzam uz $email!";
});
-// Lapas notikumi
+// Lapas pasākumi
Flight::onEvent('page.updated', function ($pageId) {
unset($_SESSION['pages'][$pageId]);
});
```
-Šī struktūra labi attīsta un paliek draudzīga iesācējiem.
+Šī struktūra labi paplašinās un paliks draudzīga iesācējiem.
## Piemēri iesācējiem
-Apskatīsim reālas dzīves scenārijus, lai parādītu, kā notikumi darbojas un kāpēc tie ir noderīgi.
+Pastaigāsim cauri dažiem reālās pasaules scenārijiem, lai parādītu, kā pasākumi darbojas un kāpēc tie ir noderīgi.
-### Piemērs 1: Lietotāja pieteikšanās ierakstīšana
+### Piemērs 1: Lietotāja pieteikšanās reģistrēšana
```php
-// 1. solis: Reģistrēt klausītāju
+// Solis 1: Reģistrēt klausītāju
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username piesakās plkst. $time");
+ error_log("$username pieteicies plkst. $time");
});
-// 2. solis: Izsaukt to savā lietojumprogrammā
+// Solis 2: Izsist to savā lietojumprogrammā
Flight::route('/login', function () {
- $username = 'bob'; // Iedomājieties, ka tas nāk no formas
+ $username = 'bob'; // Pieņemiet, ka tas nāk no formas
Flight::triggerEvent('user.login', $username);
- echo "Sveiks, $username!";
+ echo "Sveiki, $username!";
});
```
-**Kāpēc tas ir noderīgi**: Pieteikšanās kodam nav jāzina par ierakstīšanu—tas vienkārši izsauc notikumu. Vēlāk jūs varat pievienot vairāk klausītāju (piemēram, nosūtīt sveiciena e-pastu) bez izmaiņām maršrutā.
+**Kāpēc tas ir noderīgi**: Pieteikšanās kods nenojauš par reģistrēšanu—tas tikai izsisti pasākumu. Jūs vēlāk varat pievienot vairāk klausītāju (piemēram, nosūtīt sveiciena e-pastu) bez maršruta mainīšanas.
-### Piemērs 2: Jauno lietotāju paziņošana
+### Piemērs 2: Paziņošana par jauniem lietotājiem
```php
// Klausītājs jaunām reģistrācijām
Flight::onEvent('user.registered', function ($email, $name) {
- // Simulēt e-pasta sūtīšanu
+ // Simulējiet e-pasta nosūtīšanu
echo "E-pasts nosūtīts uz $email: Laipni lūdzam, $name!";
});
-// Izsaukt to, kad kāds reģistrējas
+// Izsisti to, kad kāds piesakās
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "Paldies par reģistrēšanos!";
+ echo "Paldies, ka reģistrējāties!";
});
```
-**Kāpēc tas ir noderīgi**: Reģistrācijas loģika koncentrējas uz lietotāja izveidi, bet notikums apstrādā paziņojumus. Jūs varat vēlāk pievienot vairāk klausītāju (piemēram, ierakstīt reģistrāciju) pēc nepieciešamības.
+**Kāpēc tas ir noderīgi**: Reģistrācijas loģika koncentrējas uz lietotāja radīšanu, kamēr pasākums apstrādā paziņojumus. Jūs varētu vēlāk pievienot vairāk klausītāju (piemēram, reģistrēt reģistrāciju) gadījumā, ja tas būs nepieciešams.
-### Piemērs 3: Kešatmiņas notīrīšana
+### Piemērs 3: Kešatmiņas dzēšana
```php
-// Klausītājs kešatmiņas tīrīšanai
+// Klausītājs kešatmiņas dzēšanai
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Tīra sesijas kešatmiņu, ja piemērojams
- echo "Kešatmiņa notīrīta lapai $pageId.";
+ unset($_SESSION['pages'][$pageId]); // Izmet kešatmiņu sesijā, ja nepieciešams
+ echo "Kešatmiņa dzēsta lapai $pageId.";
});
-// Izsaukt to, kad lapa ir rediģēta
+// Izsist to, kad lapa tiek rediģēta
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Iedomājieties, ka mēs atjauninājām lapu
+ // Pieņemiet, ka mēs esam atjauninājuši lapu
Flight::triggerEvent('page.updated', $pageId);
echo "Lapa $pageId atjaunināta.";
});
```
-**Kāpēc tas ir noderīgi**: Rediģēšanas kodam nav jārūpējas par kešatmiņu—tas vienkārši signalizē atjauninājumu. Citas lietojumprogrammas daļas var reaģēt pēc nepieciešamības.
+**Kāpēc tas ir noderīgi**: Rediģēšanas kods nezina par kešatmiņu—tas tikai signalizē par atjauninājumu. Citas lietojumprogrammas daļas var reaģēt, kā nepieciešams.
## Labākās prakses
-- **Skaidri nosauciet notikumus**: Izmantojiet specifiskus nosaukumus, piemēram, `'user.login'` vai `'page.updated'`, lai būtu acīmredzams, ko viņi dara.
-- **Saglabājiet klausītājus vienkāršus**: Neievietojiet lēnus vai sarežģītus uzdevumus klausītājos—saglabājiet savu lietojumprogrammu ātru.
-- **Pārbaudiet savus notikumus**: Izsauciet tos manuāli, lai nodrošinātu, ka klausītāji darbojas kā paredzēts.
-- **Izmantojiet notikumus saprātīgi**: Tie ir lieliski dekopēšanai, bet pārāk daudzi var padarīt jūsu kodu grūti saprotamu—izmantojiet tos, kad tas ir jēgpilni.
-
-Notikumu sistēma Flight PHP, ar `Flight::onEvent()` un `Flight::triggerEvent()`, sniedz jums vienkāršu, bet jaudīgu veidu, kā izveidot elastīgas lietojumprogrammas. Ļaujot dažādām jūsu lietojumprogrammas daļām sazināties viena ar otru caur notikumiem, jūs varat saglabāt savu kodu organizētu, atkārtoti izmantojamu un viegli paplašināmu. Neatkarīgi no tā, vai jūs reģistrējat darbības, sūtāt paziņojumus vai pārvaldat atjauninājumus, notikumi palīdz jums to izdarīt bez jūsu loģikas sajaukuma. Turklāt, ar iespēju pārrakstīt šīs metodes, jums ir brīvība pielāgot sistēmu jūsu vajadzībām. Sāciet ar vienu notikumu, un skatiet, kā tas transformē jūsu lietojumprogrammas struktūru!
-
-## Iebūvētie notikumi
-
-Flight PHP nāk ar dažiem iebūvētiem notikumiem, kurus varat izmantot, lai pieslēgtos ietvara dzīves ciklam. Šie notikumi tiek izsaukti konkrētos punktos pieprasījuma/atbildes ciklā, ļaujot jums izpildīt pielāgotu loģiku, kad notiek noteiktas darbības.
-
-### Iebūvēto notikumu saraksts
-- `flight.request.received`: Izsaukts, kad pieprasījums tiek saņemts, analizēts un apstrādāts.
-- `flight.route.middleware.before`: Izsaukts pēc tam, kad ir izpildīta "pirms" starpdaļa.
-- `flight.route.middleware.after`: Izsaukts pēc tam, kad ir izpildīta "pēcpusdienas" starpdaļa.
-- `flight.route.executed`: Izsaukts, kad maršruts tiek izpildīts un apstrādāts.
-- `flight.response.sent`: Izsaukts pēc tam, kad atbilde ir nosūtīta klientam.
\ No newline at end of file
+- **Nosakiet pasākumus skaidri**: Izmantojiet specifiskus nosaukumus, piemēram, `'user.login'` vai `'page.updated'`, lai būtu acīmredzams, ko viņi dara.
+- **Saglabājiet klausītājus vienkāršus**: Neievietojiet lēnus vai sarežģītus uzdevumus klausītājos—turiet savu lietojumprogrammu ātru.
+- **Testējiet savus pasākumus**: Manuāli izsistiet tos, lai pārliecinātos, ka klausītāji darbojas kā paredzēts.
+- **Izmantojiet pasākumus saprātīgi**: Tie ir lieliski, lai atsvaidzinātu, bet pārāk daudz var padarīt jūsu kodu grūti izsekojamu—izmantojiet tos, kad tas ir jēgas.
+
+Pasākumu sistēma Flight PHP, izmantojot `Flight::onEvent()` un `Flight::triggerEvent()`, piedāvā jums vienkāršu, bet spēcīgu veidu, kā veidot elastīgas lietojumprogrammas. Ļaujot dažādām jūsu lietojumprogrammas daļām sazināties viena ar otru caur pasākumiem, jūs varat saglabāt savu kodu organizētu, atkārtoti izmantojamu un viegli paplašināmu. Neatkarīgi no tā, vai reģistrējat darbības, nosūtāt paziņojumus vai pārvaldāt atjauninājumus, pasākumi palīdz to darīt bez loģikas sapīšanos. Turklāt, ar iespēju pārdefinēt šīs metodes, jums ir brīvība pielāgot sistēmu savām vajadzībām. Sāciet ar mazu pasākumu un skatieties, kā tas transformē jūsu lietojumprogrammas struktūru!
+
+## Iebūvēti pasākumi
+
+Flight PHP nāk ar dažiem iebūvētiem pasākumiem, kurus jūs varat izmantot, lai pieslēgtos rāmja dzīves ciklam. Šie pasākumi tiek izsisti noteiktos punktos pieprasījuma/atbildes ciklā, ļaujot jums izpildīt pielāgotu loģiku, kad noteiktas darbības notiek.
+
+### Iebūvēto pasākumu saraksts
+- **flight.request.received**: `function(Request $request)` Izsists, kad pieprasījums ir saņemts, analizēts un apstrādāts.
+- **flight.error**: `function(Throwable $exception)` Izsists, kad notiek kļūda pieprasījuma dzīves ciklā.
+- **flight.redirect**: `function(string $url, int $status_code)` Izsists, kad tiek uzsākta novirzīšana.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Izsists, kad kešatmiņa tiek pārbaudīta attiecīgajam atslēgai un, vai kešatmiņa ir situsi vai ne.
+- **flight.middleware.before**: `function(Route $route)` Izsists pēc tam, kad pirms starpprogrammas ir izpildīta.
+- **flight.middleware.after**: `function(Route $route)` Izsists pēc tam, kad pēc starpprogrammas ir izpildīta.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Izsists pēc tam, kad jebkura starpprogramma ir izpildīta
+- **flight.route.matched**: `function(Route $route)` Izsists, kad maršruts ir saskaņots, bet vēl nav izpildīts.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Izsists pēc tam, kad maršruts ir izpildīts un apstrādāts. `$executionTime` ir laiks, kas bija vajadzīgs maršruta izpildei (kontroliera izsaukšanai utt.).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Izsists pēc tam, kad skats ir izveidots. `$executionTime` ir laiks, kas bija vajadzīgs, lai parādītu veidni. **Piezīme: Ja jūs pārdefinējat `render` metodi, jums būs nepieciešams atkārtoti izsist šo pasākumu.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Izsists pēc tam, kad atbilde ir nosūtīta klientam. `$executionTime` ir laiks, kas bija vajadzīgs, lai izveidotu atbildi.
\ No newline at end of file
diff --git a/content/v3/pt/awesome-plugins/apm.md b/content/v3/pt/awesome-plugins/apm.md
new file mode 100644
index 0000000..38d9109
--- /dev/null
+++ b/content/v3/pt/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM Documentation
+
+Bem-vindo ao FlightPHP APM—o coach pessoal de desempenho da sua aplicação! Este guia é seu mapa para configurar, usar e dominar o Monitoramento de Desempenho de Aplicações (APM) com o FlightPHP. Seja você um caçador de requisições lentas ou apenas queira se empolgar com gráficos de latência, estamos aqui para ajudar. Vamos tornar sua aplicação mais rápida, seus usuários mais felizes e suas sessões de depuração um passeio no parque!
+
+## Por que o APM importa
+
+Imagine isto: sua aplicação é um restaurante movimentado. Sem uma maneira de rastrear quanto tempo os pedidos levam ou onde a cozinha está travando, você está adivinhando por que os clientes estão saindo irritados. O APM é seu sous-chef—ele observa cada passo, desde requisições recebidas até consultas ao 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 leva mais de 3 segundos para carregar!), e o APM te ajuda a detectar esses problemas *antes* que eles te causem dor. É uma paz de espírito proativa—menos momentos de “por que isso está quebrado?”, mais vitórias de “veja como isso funciona bem!”.
+
+## Instalação
+
+Comece com o Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Você vai precisar de:
+- **PHP 7.4+**: Mantém nossa compatibilidade com distribuições Linux LTS enquanto suporta PHP moderno.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: O framework leve que estamos potenciando.
+
+## Começando
+
+Aqui está seu passo a passo para a maravilha do APM:
+
+### 1. Registre o APM
+
+Adicione isto ao seu `index.php` ou a um arquivo `services.php` para começar a rastrear:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**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 (requisições, rotas, erros, etc.) e coleta métricas.
+- `bindEventsToFlightInstance($app)` amarra tudo à sua aplicação Flight.
+
+**Dica Pro: Amostragem**
+Se sua aplicação estiver ocupada, 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 requisições
+```
+
+Isso mantém o desempenho ágil enquanto ainda te dá dados sólidos.
+
+### 2. Configure
+
+Execute isto para criar seu `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**O que isso faz?**
+- Lança um assistente perguntando de onde vêm as métricas brutas (origem) e para onde os dados processados vão (destino).
+- O padrão é SQLite—por exemplo, `sqlite:/tmp/apm_metrics.sqlite` para origem, outro para destino.
+- Você acabará com uma configuração como:
+ ```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"
+ }
+ }
+ ```
+
+**Por que dois locais?**
+As métricas brutas se acumulam rapidamente (pense em logs não filtrados). O trabalhador as processa em um destino estruturado para o painel. Mantém as coisas organizadas!
+
+### 3. Processar Métricas com o Trabalhador
+
+O trabalhador transforma métricas brutas em dados prontos para o painel. Execute uma vez:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**O que está fazendo?**
+- Lê a partir de sua origem (por exemplo, `apm_metrics.sqlite`).
+- Processa até 100 métricas (tamanho do lote padrão) em seu destino.
+- Para quando terminar ou se não houver mais métricas.
+
+**Mantenha-o em funcionamento**
+Para aplicativos 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 elas chegam. Ótimo para desenvolvimento ou pequenas configurações.
+
+- **Crontab**:
+ Adicione isto ao seu crontab (`crontab -e`):
+ ```bash
+ * * * * * php /path/to/project/vendor/bin/runway apm:worker
+ ```
+ Executa a cada minuto—perfeito para produção.
+
+- **Tmux/Screen**:
+ Inicie uma sessão destacável:
+ ```bash
+ tmux new -s apm-worker
+ php vendor/bin/runway apm:worker --daemon
+ # Ctrl+B, depois D para destacar; `tmux attach -t apm-worker` para reconectar
+ ```
+ Mantém em funcionamento mesmo que você saia.
+
+- **Ajustes Personalizados**:
+ ```bash
+ php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
+ ```
+ - `--batch_size 50`: Processa 50 métricas por vez.
+ - `--max_messages 1000`: Para após 1000 métricas.
+ - `--timeout 300`: Sai após 5 minutos.
+
+**Por que se preocupar?**
+Sem o trabalhador, seu painel ficará vazio. Ele é a ponte entre logs brutos e insights acionáveis.
+
+### 4. Lançar o Painel
+
+Veja os vitais da sua aplicação:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**O que isso é?**
+- Levanta um servidor PHP em `http://localhost:8001/apm/dashboard`.
+- Mostra logs de requisições, rotas lentas, taxas de erro e mais.
+
+**Personalize-o**:
+```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`: Acessível de qualquer IP (útil para visualização remota).
+- `--port 8080`: Use uma porta diferente se 8001 já estiver em uso.
+- `--php-path`: Aponte para o PHP se não estiver em seu PATH.
+
+Acesse a URL no seu navegador e explore!
+
+#### Modo de Produção
+
+Para produção, você pode precisar tentar algumas técnicas para fazer o painel funcionar, já que provavelmente há firewalls e outras medidas de segurança em vigor. Aqui estão algumas opções:
+
+- **Use um Proxy Reverso**: Configure o Nginx ou Apache para encaminhar requisições para o painel.
+- **Túnel SSH**: Se você conseguir SSH na máquina, use `ssh -L 8080:localhost:8001 youruser@yourserver` para criar um túnel do painel para sua máquina local.
+- **VPN**: Se seu servidor está por trás de uma VPN, conecte-se e acesse o painel diretamente.
+- **Configurar Firewall**: Abra a porta 8001 para seu IP ou a rede do servidor. (ou qualquer que seja a porta que você configurar).
+- **Configurar Apache/Nginx**: Se você tem um servidor web na frente de sua aplicação, pode configurá-lo para um domínio ou subdomínio. Se fizer isso, defina a raiz do documento como `/path/to/your/project/vendor/flightphp/apm/dashboard`
+
+#### Quer um painel diferente?
+
+Você pode construir seu próprio painel se quiser! Olhe no diretório vendor/flightphp/apm/src/apm/presenter para ideias de como apresentar os dados para seu próprio painel!
+
+## Recursos do Painel
+
+O painel é seu HQ do APM—aqui está o que você verá:
+
+- **Log de Requisições**: Cada 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 que consomem tempo (por exemplo, “/api/heavy” em 2.5s).
+- **Rotas Mais Lentas**: Top 5 rotas por tempo médio—ótimo para identificar padrões.
+- **Taxa de Erro**: Percentagem de requisições falhando (por exemplo, 2.3% 500s).
+- **Percentis de Latência**: 95º (p95) e 99º (p99) tempos de resposta—saiba quais são seus piores cenários.
+- **Gráfico de Códigos de Resposta**: Visualize 200s, 404s, 500s ao longo do tempo.
+- **Consultas Longas/Middleware**: Top 5 chamadas lentas de banco de dados e camadas de middleware.
+- **Cache Hit/Miss**: 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.
+
+**Exemplo**:
+Uma requisição para `/users` pode mostrar:
+- Tempo Total: 150ms
+- Middleware: `AuthMiddleware->handle` (50ms)
+- Consulta: `SELECT * FROM users` (80ms)
+- Cache: Hit em `user_list` (5ms)
+
+## Adicionando Eventos Personalizados
+
+Rastreie qualquer coisa—como uma chamada de API ou processo de pagamento:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Onde isso aparece?**
+Nos detalhes de requisições do painel sob “Eventos Personalizados”—expansível com formatação JSON bonita.
+
+**Caso de Uso**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Agora você verá se essa API está arrastando sua aplicação para baixo!
+
+## Monitoramento de Banco de Dados
+
+Rastreie consultas PDO assim:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**O que você recebe**:
+- Texto da consulta (por exemplo, `SELECT * FROM users WHERE id = ?`)
+- Tempo de execução (por exemplo, 0.015s)
+- Contagem de linhas (por exemplo, 42)
+
+**Atenção**:
+- **Opcional**: Pule isto se você não precisar de rastreamento de banco de dados.
+- **Somente PdoWrapper**: PDO Core ainda não está conectado—fique ligado!
+- **Aviso de Desempenho**: Registrar cada consulta em um site com muito banco de dados pode desacelerar as coisas. Use amostragem (`$Apm = new Apm($ApmLogger, 0.1)`) para aliviar a carga.
+
+**Saída de Exemplo**:
+- Consulta: `SELECT name FROM products WHERE price > 100`
+- Tempo: 0.023s
+- Linhas: 15
+
+## Opções do Trabalhador
+
+Ajuste o trabalhador do seu jeito:
+
+- `--timeout 300`: Para após 5 minutos—bom para testes.
+- `--max_messages 500`: Limita a 500 métricas—mantém as coisas finitas.
+- `--batch_size 200`: Processa 200 de uma vez—equilibra velocidade e memória.
+- `--daemon`: Roda sem parar—ideal para monitoramento ao vivo.
+
+**Exemplo**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+Roda por uma hora, processando 100 métricas por vez.
+
+## Resolução de Problemas
+
+Trancado? Tente isto:
+
+- **Sem Dados no Painel?**
+ - O trabalhador está funcionando? Verifique `ps aux | grep apm:worker`.
+ - Os caminhos de configuração correspondem? Verifique se os DSNs do `.runway-config.json` apontam para arquivos reais.
+ - Execute `php vendor/bin/runway apm:worker` manualmente para processar métricas pendentes.
+
+- **Erros de Trabalhador?**
+ - 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 por rastros de pilha.
+
+- **Painel 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`.
+
+- **Muito Lento?**
+ - Reduza a taxa de amostragem: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Reduza o tamanho do lote: `--batch_size 20`.
\ 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 c0c75a2..aa1c6d8 100644
--- a/content/v3/pt/awesome-plugins/awesome_plugins.md
+++ b/content/v3/pt/awesome-plugins/awesome_plugins.md
@@ -6,74 +6,79 @@ Flight é incrivelmente extensível. Existem vários plugins que podem ser usado
A documentação da API é crucial para qualquer API. Ela ajuda os desenvolvedores a entender como interagir com sua API e o que esperar em troca. Existem algumas ferramentas disponíveis para ajudá-lo a gerar documentação da API para seus projetos Flight.
-- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Post do blog escrito por Daniel Schreiber sobre como usar a Especificação OpenAPI com FlightPHP para construir sua API usando uma abordagem primeiro a API.
-- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI é uma ótima ferramenta para ajudá-lo a gerar documentação da API para seus projetos Flight. É muito fácil de usar e pode ser personalizado para atender às suas necessidades. Esta é a biblioteca PHP que o ajudará a gerar a documentação Swagger.
+- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Postagem no blog escrita por Daniel Schreiber sobre como usar a Especificação OpenAPI com FlightPHP para construir sua API usando uma abordagem primeiro a API.
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI é uma ótima ferramenta para ajudá-lo a gerar documentação da API para seus projetos Flight. É muito fácil de usar e pode ser personalizado para atender às suas necessidades. Esta é a biblioteca PHP para ajudá-lo a gerar a documentação Swagger.
+
+## 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árias ferramentas APM que podem ser usadas com Flight.
+- beta[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.
## Autenticação/Autorização
-Autenticação e Autorização são cruciais para qualquer aplicação que exija controles para determinar quem pode acessar o quê.
+A autenticação e autorização são cruciais para qualquer aplicação que requer controles sobre quem pode acessar o que.
-- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permissões Flight. Esta biblioteca é uma maneira simples de adicionar permissões de nível de usuário e aplicação à sua aplicação.
+- official [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permissões do Flight. Esta biblioteca é uma maneira simples de adicionar permissões a nível de usuário e aplicação à sua aplicação.
-## Cache
+## Caching
-Cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight.
+O caching é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de caching que podem ser usadas com o Flight.
-- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache em arquivo PHP leve, simples e autônoma.
+- official [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de caching in-file PHP leve, simples e autônoma
## 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.
+As 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 o ajuda a gerenciar suas aplicações Flight.
+- official [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.
+Os 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.
- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma maneira simples e eficaz de gerenciar cookies.
## Depuração
-A depuração é crucial ao desenvolver em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração.
+A depuração é crucial ao desenvolver em seu ambiente local. Existem alguns plugins que podem melhorar sua experiência de depuração.
-- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com Flight. Ele possui 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.
-- [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 especificamente na depuração de projetos Flight.
+- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com o Flight. Ele possui 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.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o [Tracy](/awesome-plugins/tracy) manipulador de erros, este plugin adiciona alguns painéis extras para ajudar com a depuração especificamente para projetos Flight.
## Bancos de Dados
-Bancos de dados são a base da maioria das aplicações. Esta é a forma como você armazena e recupera dados. Algumas bibliotecas de banco de dados são apenas wrappers para escrever consultas e algumas são ORMs completos.
+Os 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](/awesome-plugins/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 do Flight oficial. Ótima biblioteca para recuperar e armazenar dados em seu banco de dados de forma fácil.
-- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para manter o controle de todas as alterações no banco de dados para o seu projeto.
+- official [flightphp/core PdoWrapper](/awesome-plugins/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.
+- official [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapeador ActiveRecord oficial do Flight. Ótima biblioteca para recuperar e armazenar dados facilmente em seu banco de dados.
+- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para acompanhar todas as alterações no banco de dados do seu projeto.
## Criptografia
-A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é muito 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). A coisa mais importante é nunca armazenar sua chave de criptografia em um diretório público ou comprometer em seu repositório de código.
+A criptografia é crucial para qualquer aplicação que armazene dados sensíveis. Criptografar e descriptografar os dados não é tão 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 comitá-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 usá-la é bastante simples para iniciar a criptografia e descriptografia de dados.
+- [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é relativamente simples para começar a criptografar e descriptografar dados.
## Fila de Trabalho
-Filas de trabalho são muito úteis para processar tarefas de forma assíncrona. Isso pode incluir o envio de e-mails, processamento de imagens ou qualquer coisa que não precisa ser feita em tempo real.
+As filas de trabalho são muito ú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) - Fila de Trabalho Simples é uma biblioteca que pode ser usada para processar trabalhos 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, as sessões podem ser cruciais para manter o estado e as informações de login.
+As sessões não são realmente úteis para APIs, mas para construir uma aplicação web, as sessões podem ser cruciais para manter o estado e as informações de login.
-- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sessões Flight. Esta é uma biblioteca simples de sessão que pode ser usada para armazenar e recuperar dados de sessão. Ela utiliza o gerenciamento de sessões embutido do PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessões PHP (não bloqueante, flash, segmento, criptografia de sessão). Utiliza PHP open_ssl para criptografia/descriptografia opcional de dados de sessão.
+- official [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sessão do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Utiliza o gerenciamento de sessão embutido do PHP.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessões PHP (não bloqueante, flash, segmentação, criptografia de sessão). Usa o PHP open_ssl para criptografar/descriptografar opcionais os dados da sessão.
## Modelagem
-Modelagem é essencial para qualquer aplicação web com uma interface de usuário. Existem vários mecanismos de modelagem que podem ser usados com Flight.
+A modelagem é fundamental para qualquer aplicação web com uma interface de usuário. Existem vários mecanismos de modelagem que podem ser usados com Flight.
-- obsoleto [flightphp/core View](/learn#views) - Este é um mecanismo de modelagem muito básico que faz parte do núcleo. Não é recomendado o uso se você tiver mais de algumas páginas em seu projeto.
+- deprecated [flightphp/core View](/learn#views) - Este é um mecanismo de modelagem muito básico que faz parte do núcleo. Não é recomendável usá-lo se você tiver mais de algumas páginas em seu projeto.
- [latte/latte](/awesome-plugins/latte) - Latte é um mecanismo de modelagem 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.
## Contribuindo
-Tem um plugin que gostaria de compartilhar? Envie um pedido de pull para adicioná-lo à lista!
\ No newline at end of file
+Tem um plugin que gostaria de compartilhar? Envie uma solicitação de pull para adicioná-lo à lista!
\ No newline at end of file
diff --git a/content/v3/pt/awesome-plugins/tracy_extensions.md b/content/v3/pt/awesome-plugins/tracy_extensions.md
index e9a4953..6ddb0bf 100644
--- a/content/v3/pt/awesome-plugins/tracy_extensions.md
+++ b/content/v3/pt/awesome-plugins/tracy_extensions.md
@@ -1,28 +1,28 @@
-Tracy Painel de Extensões
+Tracy Flight Painel de Extensões
=====
Este é um conjunto de extensões para tornar o trabalho com o Flight um pouco mais rico.
-- Flight - Analisar todas as variáveis do Flight.
-- Banco de Dados - Analisar todas as consultas que foram executadas na página (se você iniciar corretamente a conexão com o banco de dados)
-- Requisição - Analisar todas as variáveis `$_SERVER` e examinar todos os payloads globais (`$_GET`, `$_POST`, `$_FILES`)
-- Sessão - Analisar todas as variáveis `$_SESSION` se as sessões estiverem ativas.
+- Flight - Analise todas as variáveis do Flight.
+- Database - Analise todas as consultas que foram executadas na página (se você iniciar corretamente a conexão com o banco de dados)
+- Request - Analise todas as variáveis `$_SERVER` e examine todas as cargas úteis globais (`$_GET`, `$_POST`, `$_FILES`)
+- Session - Analise todas as variáveis `$_SESSION` se as sessões estiverem ativas.
Este é o Painel
-
+
E cada painel exibe informações muito úteis sobre sua aplicação!
-
-
-
+
+
+
-Clique [aqui](https://github.com/flightphp/tracy-extensions) para visualizar o código.
+Clique [aqui](https://github.com/flightphp/tracy-extensions) para ver o código.
Instalação
-------
-Execute `composer require flightphp/tracy-extensions --dev` e está tudo pronto!
+Execute `composer require flightphp/tracy-extensions --dev` e você está no caminho certo!
Configuração
-------
@@ -34,23 +34,23 @@ Há muito pouca configuração que você precisa fazer para começar. Você prec
use Tracy\Debugger;
use flight\debug\tracy\TracyExtensionLoader;
-// código de inicialização
+// código de bootstrap
require __DIR__ . '/vendor/autoload.php';
Debugger::enable();
-// Talvez você precise especificar seu ambiente com Debugger::enable(Debugger::DEVELOPMENT)
+// Você pode precisar especificar seu ambiente com Debugger::enable(Debugger::DEVELOPMENT)
-// se você usa conexões de banco de dados em seu aplicativo, há
-// um wrapper PDO obrigatório para usar APENAS EM DESENVOLVIMENTO (não em produção por favor!)
-// Tem os mesmos parâmetros que uma conexão PDO regular
+// se você usar conexões de banco de dados em seu aplicativo, há um
+// wrapper PDO necessário para usar APENAS EM DESENVOLVIMENTO (não em produção, por favor!)
+// Ele tem os mesmos parâmetros que uma conexão PDO regular
$pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass');
// ou se você anexar isso ao framework Flight
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']);
-// agora, sempre que você fizer uma consulta, ela capturará o tempo, a consulta e os parâmetros
+// agora, sempre que você fizer uma consulta, ela irá capturar o tempo, consulta e parâmetros
// Isso conecta os pontos
if(Debugger::$showBar === true) {
- // Isto precisa ser falso ou Tracy não pode renderizar de fato :(
+ // Isso precisa ser falso ou Tracy não pode realmente renderizar :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
@@ -63,11 +63,12 @@ Flight::start();
## Configuração Adicional
### Dados da Sessão
-Se você tiver um manipulador de sessão personalizado (como ghostff/session), você pode passar qualquer array de dados de sessão para Tracy e ele os exibirá automaticamente para você. Você passa com a chave `session_data` no segundo parâmetro do construtor `TracyExtensionLoader`.
+Se você tiver um manipulador de sessão personalizado (como ghostff/session), você pode passar qualquer array de dados de sessão para o Tracy e ele irá automaticamente exibi-lo para você. Você passa isso com a chave `session_data` no segundo parâmetro do construtor `TracyExtensionLoader`.
```php
use Ghostff\Session\Session;
+// ou use flight\Session;
require 'vendor/autoload.php';
@@ -76,7 +77,7 @@ $app = Flight::app();
$app->register('session', Session::class);
if(Debugger::$showBar === true) {
- // Isto precisa ser falso ou Tracy não pode renderizar de fato :(
+ // Isso precisa ser falso ou Tracy não pode realmente renderizar :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -88,7 +89,7 @@ Flight::start();
### Latte
-Se você tiver o Latte instalado em seu projeto, você pode usar o painel do Latte para analisar seus modelos. Você pode passar a instância do Latte para o construtor `TracyExtensionLoader` com a chave `latte` no segundo parâmetro.
+Se você tiver o Latte instalado em seu projeto, pode usar o painel do Latte para analisar seus templates. Você pode passar a instância do Latte para o construtor `TracyExtensionLoader` com a chave `latte` no segundo parâmetro.
```php
@@ -101,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // aqui é onde você adiciona o Painel do Latte ao Tracy
+ // é aqui que você adiciona o Painel Latte ao Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // Isto precisa ser falso ou Tracy não pode renderizar de fato :(
+ // Isso precisa ser falso ou Tracy não pode realmente renderizar :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/pt/learn/events.md b/content/v3/pt/learn/events.md
index cf5f33f..6feb237 100644
--- a/content/v3/pt/learn/events.md
+++ b/content/v3/pt/learn/events.md
@@ -1,41 +1,41 @@
# Sistema de Eventos no Flight PHP (v3.15.0+)
-O Flight PHP introduz um sistema de eventos leve e intuitivo que permite registrar e acionar eventos personalizados em sua aplicação. Com a adição de `Flight::onEvent()` e `Flight::triggerEvent()`, agora você pode se conectar a momentos-chave do ciclo de vida do seu aplicativo ou definir seus próprios eventos para tornar seu código mais modular e extensível. Estes métodos fazem parte dos **métodos mapeáveis** do Flight, o que significa que você pode substituir seu comportamento para atender às suas necessidades.
+O Flight PHP introduz um sistema de eventos leve e intuitivo que permite registrar e acionar eventos personalizados em sua aplicação. Com a adição de `Flight::onEvent()` e `Flight::triggerEvent()`, você agora pode se conectar a momentos-chave do ciclo de vida do seu aplicativo ou definir seus próprios eventos para tornar seu código mais modular e extensível. Esses métodos fazem parte dos **métodos mapeáveis** do Flight, o que significa que você pode sobrescrever seu comportamento para atender às suas necessidades.
-Este guia cobre tudo que você precisa saber para começar com eventos, incluindo por que eles são valiosos, como usá-los e exemplos práticos para ajudar iniciantes a entender seu poder.
+Este guia cobre tudo o que você precisa saber para começar a trabalhar com eventos, incluindo por que eles são valiosos, como usá-los e exemplos práticos para ajudar iniciantes a entender seu poder.
-## Por Que Usar Eventos?
+## Por que Usar Eventos?
-Eventos permitem que você separe diferentes partes da sua aplicação para que não dependam muito umas das outras. Essa separação—frequentemente chamada de **desacoplamento**—torna seu código mais fácil de atualizar, estender ou depurar. Em vez de escrever tudo em um único bloco grande, você pode dividir sua lógica em partes menores e independentes que respondem a ações específicas (eventos).
+Eventos permitem que você separe diferentes partes da sua aplicação para que não dependam muito uma da outra. Essa separação—frequentemente chamada de **desacoplamento**—torna seu código mais fácil de atualizar, estender ou depurar. Em vez de escrever tudo em um único bloco grande, você pode dividir sua lógica em partes menores e independentes que respondem a ações específicas (eventos).
Imagine que você está construindo um aplicativo de blog:
-- Quando um usuário posta um comentário, você pode querer:
+- Quando um usuário publica um comentário, você pode querer:
- Salvar o comentário no banco de dados.
- - Enviar um e-mail para o proprietário do blog.
+ - Enviar um e-mail ao proprietário do blog.
- Registrar a ação para segurança.
-Sem eventos, você cramaria tudo em uma única função. Com eventos, você pode dividi-lo: uma parte salva o comentário, outra aciona um evento como `'comment.posted'`, e ouvintes separados lidam com o e-mail e o registro. Isso mantém seu código mais claro e lhe permite adicionar ou remover funcionalidades (como notificações) sem tocar na lógica central.
+Sem eventos, você colocaria tudo isso em uma única função. Com eventos, você pode separá-los: uma parte salva o comentário, outra aciona um evento como `'comment.posted'`, e ouvintes separados lidam com o e-mail e o registro. Isso mantém seu código mais limpo e permite que você adicione ou remova recursos (como notificações) sem tocar na lógica principal.
### Usos Comuns
-- **Registro**: Registrar ações como logins ou erros sem sobrecarregar seu código principal.
-- **Notificações**: Enviar e-mails ou alertas quando algo acontece.
-- **Atualizações**: Atualizar caches ou notificar outros sistemas sobre mudanças.
+- **Registro**: Registre ações como logins ou erros sem poluir seu código principal.
+- **Notificações**: Envie e-mails ou alertas quando algo acontecer.
+- **Atualizações**: Atualize caches ou notifique outros sistemas sobre mudanças.
## Registrando Ouvintes de Eventos
-Para ouvir um evento, use `Flight::onEvent()`. Este método permite que você defina o que deve acontecer quando um evento ocorrer.
+Para ouvir um evento, use `Flight::onEvent()`. Este método permite que você defina o que deve acontecer quando um evento ocorre.
### Sintaxe
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Um nome para seu evento (por exemplo, `'user.login'`).
+- `$event`: Um nome para o seu evento (por exemplo, `'user.login'`).
- `$callback`: A função a ser executada quando o evento for acionado.
### Como Funciona
-Você "se inscreve" em um evento dizendo ao Flight o que fazer quando ele acontece. O callback pode aceitar argumentos passados do acionador do evento.
+Você "se inscreve" em um evento informando ao Flight o que fazer quando ele acontece. O callback pode aceitar argumentos passados do acionador do evento.
-O sistema de eventos do Flight é síncrono, o que significa que cada ouvinte de evento é executado em sequência, um após o outro. Quando você aciona um evento, todos os ouvintes registrados para esse evento serão executados até a conclusão antes que seu código continue. Isso é importante de entender, pois difere de sistemas de eventos assíncronos onde os ouvintes podem ser executados em paralelo ou em um momento posterior.
+O sistema de eventos do Flight é síncrono, o que significa que cada ouvinte de evento é executado em sequência, um após o outro. Quando você aciona um evento, todos os ouvintes registrados para esse evento serão executados até a conclusão antes que seu código continue. Isso é importante entender, pois difere de sistemas de eventos assíncronos onde os ouvintes podem ser executados em paralelo ou em um momento posterior.
### Exemplo Simples
```php
@@ -43,39 +43,39 @@ Flight::onEvent('user.login', function ($username) {
echo "Bem-vindo de volta, $username!";
});
```
-Aqui, quando o evento `'user.login'` é acionado, ele cumprimenta o usuário pelo nome.
+Aqui, quando o evento `'user.login'` é acionado, cumprimenta o usuário pelo nome.
### Pontos Chave
-- Você pode adicionar múltiplos ouvintes ao mesmo evento—eles serão executados na ordem em que foram registrados.
+- Você pode adicionar vários ouvintes ao mesmo evento—eles serão executados na ordem em que você os registrou.
- O callback pode ser uma função, uma função anônima ou um método de uma classe.
## Acionando Eventos
-Para fazer um evento acontecer, use `Flight::triggerEvent()`. Isso diz ao Flight para executar todos os ouvintes registrados para esse evento, passando qualquer dado que você fornecer.
+Para fazer um evento acontecer, use `Flight::triggerEvent()`. Isso informa ao Flight para executar todos os ouvintes registrados para esse evento, passando qualquer dado que você fornecer.
### Sintaxe
```php
Flight::triggerEvent(string $event, ...$args): void
```
- `$event`: O nome do evento que você está acionando (deve corresponder a um evento registrado).
-- `...$args`: Argumentos opcionais a serem enviados aos ouvintes (podem ser qualquer número de argumentos).
+- `...$args`: Argumentos opcionais a serem enviados aos ouvintes (pode ser qualquer número de argumentos).
### Exemplo Simples
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Isso aciona o evento `'user.login'` e envia `'alice'` para o ouvinte que definimos anteriormente, que irá gerar: `Bem-vindo de volta, alice!`.
+Isso aciona o evento `'user.login'` e envia `'alice'` para o ouvinte que definimos anteriormente, que irá produzir: `Bem-vindo de volta, alice!`.
### Pontos Chave
-- Se nenhum ouvinte estiver registrado, nada acontecerá—seu aplicativo não quebrará.
-- Use o operador de spread (`...`) para passar múltiplos argumentos de forma flexível.
+- Se nenhum ouvinte estiver registrado, nada acontece—seu aplicativo não quebrará.
+- Use o operador de propagação (`...`) para passar múltiplos argumentos de forma flexível.
### Registrando Ouvintes de Eventos
...
-**Interrompendo Ouvintes Futuros**:
+**Parando Ouvintes Futuro**:
Se um ouvinte retornar `false`, nenhum ouvinte adicional para esse evento será executado. Isso permite que você interrompa a cadeia de eventos com base em condições específicas. Lembre-se, a ordem dos ouvintes importa, pois o primeiro a retornar `false` impedirá o restante de serem executados.
**Exemplo**:
@@ -83,7 +83,7 @@ Se um ouvinte retornar `false`, nenhum ouvinte adicional para esse evento será
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // Interrompe ouvintes subsequentes
+ return false; // Para ouvintes subsequentes
}
});
Flight::onEvent('user.login', function ($username) {
@@ -91,32 +91,32 @@ Flight::onEvent('user.login', function ($username) {
});
```
-## Substituindo Métodos de Evento
+## Sobrescrevendo Métodos de Evento
-`Flight::onEvent()` e `Flight::triggerEvent()` estão disponíveis para serem [estendidos](/learn/extending), o que significa que você pode redefinir como eles funcionam. Isso é ótimo para usuários avançados que desejam personalizar o sistema de eventos, como adicionar registro ou alterar como os eventos são enviados.
+`Flight::onEvent()` e `Flight::triggerEvent()` estão disponíveis para serem [estendidos](/learn/extending), o que significa que você pode redefinir como eles funcionam. Isso é ótimo para usuários avançados que desejam personalizar o sistema de eventos, como adicionar registro ou alterar como os eventos são despachados.
### Exemplo: Personalizando `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // Registre cada registro de evento
+ // Registrar cada registro de evento
error_log("Novo ouvinte de evento adicionado para: $event");
- // Chame o comportamento padrão (supondo um sistema de eventos interno)
+ // Chame o comportamento padrão (assumindo um sistema de eventos interno)
Flight::_onEvent($event, $callback);
});
```
-Agora, toda vez que você registra um evento, ele é registrado antes de prosseguir.
+Agora, toda vez que você registrar um evento, ele será registrado antes de prosseguir.
-### Por Que Substituir?
-- Adicionar depuração ou monitoramento.
-- Restringir eventos em determinados ambientes (por exemplo, desativar em testes).
-- Integrar-se com uma biblioteca de eventos diferente.
+### Por que Sobrescrever?
+- Adicione depuração ou monitoramento.
+- Restringir eventos em certos ambientes (por exemplo, desabilite em testes).
+- Integre-se com uma biblioteca de eventos diferente.
## Onde Colocar Seus Eventos
-Como iniciante, você pode se perguntar: *onde registro todos esses eventos na minha aplicação?* A simplicidade do Flight significa que não há uma regra rígida—você pode colocá-los onde fizer sentido para seu projeto. No entanto, mantê-los organizados ajuda você a manter seu código à medida que seu aplicativo cresce. Aqui estão algumas opções práticas e melhores práticas, adaptadas à natureza leve do Flight:
+Como iniciante, você pode se perguntar: *onde registro todos esses eventos no meu aplicativo?* A simplicidade do Flight significa que não há uma regra estrita—você pode colocá-los onde fizer sentido para seu projeto. No entanto, mantê-los organizados ajuda a manter seu código à medida que seu aplicativo cresce. Aqui estão algumas opções práticas e melhores práticas, adaptadas à natureza leve do Flight:
-### Opção 1: No Seu `index.php` Principal
-Para aplicativos pequenos ou protótipos rápidos, você pode registrar eventos diretamente em seu arquivo `index.php` juntamente com suas rotas. Isso mantém tudo em um só lugar, o que é aceitável quando a simplicidade é sua prioridade.
+### Opção 1: No Seu Principal `index.php`
+Para pequenos aplicativos ou protótipos rápidos, você pode registrar eventos diretamente no seu arquivo `index.php` junto com suas rotas. Isso mantém tudo em um só lugar, o que é aceitável quando a simplicidade é sua prioridade.
```php
require 'vendor/autoload.php';
@@ -130,7 +130,7 @@ Flight::onEvent('user.login', function ($username) {
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Conectado!";
+ echo "Logado!";
});
Flight::start();
@@ -138,8 +138,8 @@ Flight::start();
- **Prós**: Simples, sem arquivos extras, ótimo para pequenos projetos.
- **Contras**: Pode ficar bagunçado à medida que seu aplicativo cresce com mais eventos e rotas.
-### Opção 2: Um Arquivo `events.php` Separado
-Para um aplicativo um pouco maior, considere mover os registros de eventos para um arquivo dedicado como `app/config/events.php`. Inclua este arquivo em seu `index.php` antes de suas rotas. Isso imita como as rotas costumam ser organizadas em `app/config/routes.php` nos projetos do Flight.
+### Opção 2: Um Arquivo Separado `events.php`
+Para um aplicativo um pouco maior, considere mover os registros de eventos para um arquivo dedicado, como `app/config/events.php`. Inclua este arquivo no seu `index.php` antes das suas rotas. Isso imita como as rotas são frequentemente organizadas em `app/config/routes.php` em projetos Flight.
```php
// app/config/events.php
@@ -160,16 +160,16 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Conectado!";
+ echo "Logado!";
});
Flight::start();
```
- **Prós**: Mantém `index.php` focado em rotas, organiza eventos logicamente, fácil de encontrar e editar.
-- **Contras**: Adiciona um pequeno pouco de estrutura, o que pode parecer excessivo para aplicativos muito pequenos.
+- **Contras**: Adiciona um pequeno grau de estrutura, o que pode parecer exagero para aplicativos muito pequenos.
### Opção 3: Perto de Onde Eles São Acionados
-Outra abordagem é registrar eventos perto de onde eles são acionados, como dentro de um controlador ou definição de rota. Isso funciona bem se um evento é específico de uma parte do seu aplicativo.
+Outra abordagem é registrar eventos perto de onde eles são acionados, como dentro de um controlador ou definição de rota. Isso funciona bem se um evento for específico de uma parte do seu aplicativo.
```php
Flight::route('/signup', function () {
@@ -180,28 +180,28 @@ Flight::route('/signup', function () {
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Registrado!";
+ echo "Inscrito!";
});
```
- **Prós**: Mantém o código relacionado junto, bom para recursos isolados.
-- **Contras**: Espalha registros de eventos, dificultando a visualização de todos os eventos de uma vez; riscos de registros duplicados se não tomar cuidado.
+- **Contras**: Espalha registros de eventos, tornando mais difícil ver todos os eventos de uma vez; riscos de registros duplicados se não tiver cuidado.
### Melhor Prática para Flight
-- **Começar Simples**: Para aplicativos pequenos, coloque eventos em `index.php`. É rápido e alinha-se com o minimalismo do Flight.
-- **Crescer de Forma Inteligente**: À medida que seu aplicativo se expande (por exemplo, mais de 5-10 eventos), use um arquivo `app/config/events.php`. É um passo natural, como organizar rotas, e mantém seu código limpo sem adicionar estruturas complexas.
-- **Evitar Sobrecarga de Engenharia**: Não crie uma classe ou diretório de "gerenciador de eventos" completo a menos que seu aplicativo cresça muito—o Flight prospera na simplicidade, então mantenha-o leve.
+- **Comece Simples**: Para aplicativos pequenos, coloque eventos em `index.php`. É rápido e alinhado com o minimalismo do Flight.
+- **Cresça Inteligentemente**: À medida que seu aplicativo se expande (por exemplo, mais de 5-10 eventos), use um arquivo `app/config/events.php`. É um passo natural, como organizar rotas, e mantém seu código arrumado sem adicionar frameworks complexos.
+- **Evite Sobrecarga de Engenharia**: Não crie uma classe ou diretório de “gerenciador de eventos” completo, a menos que seu aplicativo fique enorme—Flight prospera na simplicidade, então mantenha leve.
-### Dica: Agrupar por Propósito
-No `events.php`, agrupe eventos relacionados (por exemplo, todos os eventos relacionados ao usuário juntos) com comentários para clareza:
+### Dica: Agrupe por Objetivo
+Em `events.php`, agrupe eventos relacionados (por exemplo, todos os eventos relacionados a usuários juntos) com comentários para clareza:
```php
// app/config/events.php
-// Eventos do Usuário
+// Eventos de Usuário
Flight::onEvent('user.login', function ($username) {
error_log("$username fez login");
});
Flight::onEvent('user.registered', function ($email) {
- echo "Bem-vindo ao $email!";
+ echo "Bem-vindo a $email!";
});
// Eventos de Página
@@ -210,34 +210,34 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-Essa estrutura escala bem e continua amigável para iniciantes.
+Essa estrutura se escala bem e permanece amigável para iniciantes.
## Exemplos para Iniciantes
-Vamos percorrer alguns cenários do mundo real para mostrar como os eventos funcionam e por que eles são úteis.
+Vamos passar por alguns cenários da vida real para mostrar como os eventos funcionam e por que são úteis.
-### Exemplo 1: Registrando um Login de Usuário
+### Exemplo 1: Registro de Um Login de Usuário
```php
-// Passo 1: Registrar um ouvinte
+// Etapa 1: Registrar um ouvinte
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
error_log("$username fez login em $time");
});
-// Passo 2: Acionar no seu aplicativo
+// Etapa 2: Acionar no seu aplicativo
Flight::route('/login', function () {
$username = 'bob'; // Suponha que isso venha de um formulário
Flight::triggerEvent('user.login', $username);
echo "Oi, $username!";
});
```
-**Por que isso é útil**: O código de login não precisa saber sobre logging—ele apenas aciona o evento. Você pode adicionar mais ouvintes depois (por exemplo, enviar um e-mail de boas-vindas) sem alterar a rota.
+**Por que é Útil**: O código de login não precisa saber sobre o registro—ele apenas aciona o evento. Você pode adicionar mais ouvintes mais tarde (por exemplo, enviar um e-mail de boas-vindas) sem alterar a rota.
-### Exemplo 2: Notificando Sobre Novos Usuários
+### Exemplo 2: Notificando sobre Novos Usuários
```php
-// Ouvinte para novos registros
+// Ouvinte para novas inscrições
Flight::onEvent('user.registered', function ($email, $name) {
- // Simule o envio de um e-mail
+ // Simular o envio de um e-mail
echo "E-mail enviado para $email: Bem-vindo, $name!";
});
@@ -249,13 +249,13 @@ Flight::route('/signup', function () {
echo "Obrigado por se inscrever!";
});
```
-**Por que isso é útil**: A lógica de inscrição foca na criação do usuário, enquanto o evento lida com as notificações. Você poderia adicionar mais ouvintes depois (por exemplo, registrar a inscrição).
+**Por que é Útil**: A lógica de inscrição se concentra em criar o usuário, enquanto o evento lida com notificações. Você poderia adicionar mais ouvintes (por exemplo, registrar a inscrição) mais tarde.
-### Exemplo 3: Limpando um Cache
+### Exemplo 3: Limpando Um Cache
```php
// Ouvinte para limpar um cache
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Limpe o cache da sessão, se aplicável
+ unset($_SESSION['pages'][$pageId]); // Limpar cache de sessão se aplicável
echo "Cache limpo para a página $pageId.";
});
@@ -266,24 +266,30 @@ Flight::route('/edit-page/(@id)', function ($pageId) {
echo "Página $pageId atualizada.";
});
```
-**Por que isso é útil**: O código de edição não se preocupa com o cache—ele apenas sinaliza a atualização. Outras partes do aplicativo podem reagir conforme necessário.
+**Por que é Útil**: O código de edição não se preocupa com o cache—ele apenas sinaliza a atualização. Outras partes do aplicativo podem reagir conforme necessário.
## Melhores Práticas
-- **Nomeie Eventos Claramente**: Use nomes específicos como `'user.login'` ou `'page.updated'` para que fique óbvio o que eles fazem.
-- **Mantenha Ouvintes Simples**: Não coloque tarefas lentas ou complexas em ouvintes—mantenha seu aplicativo rápido.
-- **Teste Seus Eventos**: Acione-os manualmente para garantir que os ouvintes funcionam como esperado.
+- **Nomeie os Eventos Claramente**: Use nomes específicos como `'user.login'` ou `'page.updated'` para que fique óbvio o que eles fazem.
+- **Mantenha os Ouvintes Simples**: Não coloque tarefas lentas ou complexas em ouvintes—mantenha seu aplicativo rápido.
+- **Teste Seus Eventos**: Acione-os manualmente para garantir que os ouvintes funcionem como esperado.
- **Use Eventos Com Sabedoria**: Eles são ótimos para desacoplamento, mas muitos podem tornar seu código difícil de seguir—use-os quando fizer sentido.
-O sistema de eventos no Flight PHP, com `Flight::onEvent()` e `Flight::triggerEvent()`, oferece uma maneira simples e poderosa de construir aplicações flexíveis. Ao permitir que diferentes partes do seu aplicativo se comuniquem entre si por meio de eventos, você pode manter seu código organizado, reutilizável e fácil de expandir. Seja registrando ações, enviando notificações ou gerenciando atualizações, os eventos ajudam você a fazer isso sem emaranhar sua lógica. Além disso, com a capacidade de substituir esses métodos, você tem a liberdade de personalizar o sistema de acordo com suas necessidades. Comece pequeno com um único evento e veja como ele transforma a estrutura do seu aplicativo!
+O sistema de eventos no Flight PHP, com `Flight::onEvent()` e `Flight::triggerEvent()`, oferece a você uma maneira simples, mas poderosa, de construir aplicativos flexíveis. Ao permitir que diferentes partes do seu aplicativo se comuniquem através de eventos, você pode manter seu código organizado, reutilizável e fácil de expandir. Se você está registrando ações, enviando notificações ou gerenciando atualizações, os eventos ajudam você a fazer isso sem emaranhar sua lógica. Além disso, com a capacidade de sobrescrever esses métodos, você tem a liberdade de adaptar o sistema às suas necessidades. Comece pequeno com um único evento e veja como isso transforma a estrutura do seu aplicativo!
-## Eventos Integrados
+## Eventos Embutidos
-O Flight PHP vem com alguns eventos integrados que você pode usar para se conectar ao ciclo de vida do framework. Esses eventos são acionados em pontos específicos do ciclo de solicitação/resposta, permitindo que você execute lógica personalizada quando certas ações ocorrem.
+O Flight PHP vem com alguns eventos embutidos que você pode usar para se conectar ao ciclo de vida do framework. Esses eventos são acionados em pontos específicos do ciclo de requisição/resposta, permitindo que você execute lógica personalizada quando certas ações ocorrerem.
-### Lista de Eventos Integrados
-- `flight.request.received`: Acionado quando uma solicitação é recebida, analisada e processada.
-- `flight.route.middleware.before`: Acionado após a execução do middleware anterior.
-- `flight.route.middleware.after`: Acionado após a execução do middleware posterior.
-- `flight.route.executed`: Acionado após uma rota ser executada e processada.
-- `flight.response.sent`: Acionado após uma resposta ser enviada ao cliente.
\ No newline at end of file
+### Lista de Eventos Embutidos
+- **flight.request.received**: `function(Request $request)` Acionado quando uma requisição é recebida, analisada e processada.
+- **flight.error**: `function(Throwable $exception)` Acionado quando um erro ocorre durante o ciclo de requisição.
+- **flight.redirect**: `function(string $url, int $status_code)` Acionado quando um redirecionamento é iniciado.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Acionado quando o cache é verificado para uma chave específica e se houve acerto ou falha no cache.
+- **flight.middleware.before**: `function(Route $route)` Acionado após a execução do middleware de antes.
+- **flight.middleware.after**: `function(Route $route)` Acionado após a execução do middleware de depois.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Acionado após qualquer middleware ser executado.
+- **flight.route.matched**: `function(Route $route)` Acionado quando uma rota é correspondente, mas ainda não foi executada.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Acionado após uma rota ser executada e processada. `$executionTime` é o tempo que levou para executar a rota (chamar o controlador, etc).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Acionado após uma visualização ser renderizada. `$executionTime` é o tempo que levou para renderizar o template. **Nota: Se você sobrescrever o método `render`, precisará reverter este evento.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Acionado após uma resposta ser enviada ao cliente. `$executionTime` é o tempo que levou para construir a resposta.
\ No newline at end of file
diff --git a/content/v3/ru/awesome-plugins/apm.md b/content/v3/ru/awesome-plugins/apm.md
new file mode 100644
index 0000000..63e002e
--- /dev/null
+++ b/content/v3/ru/awesome-plugins/apm.md
@@ -0,0 +1,278 @@
+# Документация FlightPHP APM
+
+Добро пожаловать в FlightPHP APM — ваш личный тренер по производительности приложения! Этот гайд — ваша дорожная карта по настройке, использованию и освоению мониторинга производительности приложений (APM) с FlightPHP. Независимо от того, ищете ли вы медленные запросы или просто хотите поразмышлять над графиками задержки, мы готовы помочь. Давайте сделаем ваше приложение быстрее, ваших пользователей счастливее, а ваши сессии отладки более легкими!
+
+## Почему важен APM
+
+Представьте это: ваше приложение — это загруженный ресторан. Без способа отследить, сколько времени занимает выполнение заказов, или где кухня буксует, вы гадали, почему клиенты уходят недовольными. APM — это ваш помощник — он следит за каждым шагом, от входящих запросов до запросов к базе данных, и сигнализирует о чем угодно, что замедляет вас. Медленные страницы теряют пользователей (исследования показывают, что 53% уходят, если сайт загружается более 3 секунд!), и APM помогает вам обнаружить эти проблемы *до* того, как они начнут беспокоить. Это проактивное спокойствие — меньше моментов “почему это сломано?”, больше “посмотрите, как быстро это работает!” побед.
+
+## Установка
+
+Начните с Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Вам понадобится:
+- **PHP 7.4+**: Обеспечивает совместимость с LTS дистрибутивами Linux, поддерживая современный PHP.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легковесный фреймворк, который мы усиливаем.
+
+## Начало работы
+
+Вот шаг за шагом к великолепию APM:
+
+### 1. Зарегистрируйте APM
+
+Вставьте это в ваш `index.php` или файл `services.php`, чтобы начать отслеживание:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Что здесь происходит?**
+- `LoggerFactory::create()` берет вашу конфигурацию (больше об этом скоро) и настраивает логгер — по умолчанию SQLite.
+- `Apm` — это звезда — он слушает события Flight (запросы, маршруты, ошибки и т. д.) и собирает метрики.
+- `bindEventsToFlightInstance($app)` связывает всё это с вашим приложением Flight.
+
+**Совет профессионала: выборка**
+Если ваше приложение загружено, ведение учета *каждого* запроса может перегружать систему. Используйте коэффициент выборки (от 0.0 до 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Логирует 10% запросов
+```
+
+Это позволяет поддерживать производительность на высоком уровне, предоставляя при этом надежные данные.
+
+### 2. Настройка
+
+Запустите это, чтобы создать ваш файл `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Что это делает?**
+- Запускает мастера, который спрашивает, откуда поступают сырые метрики (источник) и куда идут обработанные данные (назначение).
+- По умолчанию используется SQLite — например, `sqlite:/tmp/apm_metrics.sqlite` для источника, другой для назначения.
+- В конце у вас будет конфигурация вроде:
+ ```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"
+ }
+ }
+ ```
+
+**Почему две локации?**
+Сырые метрики накапливаются быстро (подумайте об нефильтрованных логах). Обработчик преобразует их в структурированное назначение для дашборда. Держит всё в порядке!
+
+### 3. Обработка метрик с помощью рабочего процесса
+
+Рабочий процесс преобразует сырые метрики в данные, готовые для дашборда. Запустите его один раз:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**Что он делает?**
+- Читает из вашего источника (например, `apm_metrics.sqlite`).
+- Обрабатывает до 100 метрик (размер партии по умолчанию) в ваше назначение.
+- Останавливается, когда все сделано или если метрики отсутствуют.
+
+**Держите его запущенным**
+Для работающих приложений вы захотите непрерывную обработку. Вот ваши варианты:
+
+- **Режим демона**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ Работает вечно, обрабатывая метрики по мере их поступления. Отлично подходит для разработки или небольших настроек.
+
+- **Crontab**:
+ Добавьте это в cron (`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`, чтобы снова подключиться
+ ```
+ Держит его запущенным, даже если вы выйдете.
+
+- **Пользовательские настройки**:
+ ```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 минут.
+
+**Почему это важно?**
+Без рабочего процесса ваш дашборд пуст. Это мост между сырыми логами и действительными выводами доступной информации.
+
+### 4. Запуск дашборда
+
+Посмотрите на жизненные показатели вашего приложения:
+
+```bash
+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.
+
+Перейдите по 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`
+
+#### Хотите другой дашборд?
+
+Вы можете создать свой собственный дашборд, если захотите! Посмотрите на каталог vendor/flightphp/apm/src/apm/presenter для идей о том, как представить данные для вашего собственного дашборда!
+
+## Функции дашборда
+
+Дашборд — это ваша APM база — вот что вы увидите:
+
+- **Журнал запросов**: Каждый запрос с временной меткой, URL, кодом ответа и общим временем. Нажмите "Подробности", чтобы увидеть промежуточное ПО, запросы и ошибки.
+- **Самые медленные запросы**: Топ-5 запросов, занимающих время (например, “/api/heavy” за 2.5с).
+- **Самые медленные маршруты**: Топ-5 маршрутов по среднему времени — отлично для выявления паттернов.
+- **Процент ошибок**: Процент запросов, которые завершаются ошибкой (например, 2.3% 500s).
+- **Латентные перцентили**: 95-й (p95) и 99-й (p99) времена ответа — знайте свои наихудшие сценарии.
+- **График кодов ответов**: Визуализируйте 200s, 404s, 500s с течением времени.
+- **Долгие запросы/промежуточное ПО**: Топ-5 медленных запросов к базе данных и слоев промежуточного ПО.
+- **Попадание/промах кеша**: Как часто ваш кеш выручает.
+
+**Дополнительно**:
+- Фильтры по «Последнему часу», «Последнему дню» или «Последней неделе».
+- Переключатель темной темы для тех поздних сессий.
+
+**Пример**:
+Запрос к `/users` может показать:
+- Общее время: 150ms
+- Промежуточное ПО: `AuthMiddleware->handle` (50ms)
+- Запрос: `SELECT * FROM users` (80ms)
+- Кеш: Попадание на `user_list` (5ms)
+
+## Добавление пользовательских событий
+
+Отслеживайте всё — например, вызов API или процесс оплаты:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Где это появится?**
+В подробностях запроса на дашборде под "Пользовательскими событиями" — разворачивается с красивым JSON-форматом.
+
+**Сценарий использования**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Теперь вы увидите, если этот API замедляет ваше приложение!
+
+## Мониторинг базы данных
+
+Отслеживайте запросы PDO таким образом:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Что вы получаете**:
+- Текст запроса (например, `SELECT * FROM users WHERE id = ?`)
+- Время выполнения (например, 0.015s)
+- Количество строк (например, 42)
+
+**Обратите внимание**:
+- **Необязательно**: Пропустите это, если вам не нужно отслеживание БД.
+- **Только PdoWrapper**: Основной PDO пока не подключен — следите за обновлениями!
+- **Предупреждение по производительности**: Ведение учета каждого запроса на сайте с высокой нагрузкой на БД может замедлить работу. Используйте выборку (`$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`: Работает без остановки — идеально для живого мониторинга.
+
+**Пример**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+Работает в течение часа, обрабатывая 100 метрик за раз.
+
+## Устранение неполадок
+
+Застряли? Попробуйте это:
+
+- **Нет данных на дашборде?**
+ - Работает ли рабочий процесс? Проверьте `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 на наличие трассировок стека.
+
+- **Дашборд не запускается?**
+ - Порт 8001 занят? Используйте `--port 8080`.
+ - PHP не найден? Используйте `--php-path /usr/bin/php`.
+ - Брандмауэр блокирует? Откройте порт или используйте `--host localhost`.
+
+- **Слишком медленно?**
+ - Уменьшите коэффициент выборки: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Уменьшите размер партии: `--batch_size 20`.
\ 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 2cb94bc..3e6f455 100644
--- a/content/v3/ru/awesome-plugins/awesome_plugins.md
+++ b/content/v3/ru/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
-# Потрясающие Плагины
+# Потрясающие плагины
-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 сначала".
-- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI - отличный инструмент для помощи в генерации документации API для ваших проектов Flight. Он очень прост в использовании и может быть настроен под ваши Bedürfnisse. Это PHP-библиотека, которая помогает вам генерировать документацию Swagger.
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — это отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это библиотека PHP, которая помогает вам создавать документацию Swagger.
+
+## Мониторинг производительности приложения (APM)
+
+Мониторинг производительности приложения (APM) имеет решающее значение для любого приложения. Он помогает вам понять, как ваше приложение работает и где возникают узкие места. Существует множество инструментов APM, которые можно использовать с Flight.
+- beta[flightphp/apm](/awesome-plugins/apm) - Flight APM — это простая библиотека APM, которую можно использовать для мониторинга ваших приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помогает выявлять узкие места.
## Аутентификация/Авторизация
-Аутентификация и Авторизация имеют решающее значение для любого приложения, которое требует контроля доступа.
+Аутентификация и авторизация являются решающими для любого приложения, которое требует контроля о том, кто может получить доступ к чему.
-- официальный [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека разрешений Flight. Эта библиотека является простым способом добавления разрешений на уровне пользователя и приложения в ваше приложение.
+- official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека прав доступа Flight. Эта библиотека предоставляет простой способ добавить права доступа на уровне пользователя и приложения в ваше приложение.
## Кэширование
-Кэширование - отличный способ ускорить ваше приложение. Существует несколько библиотек кэширования, которые могут быть использованы с 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.
-## Куки
+## 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. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Также очень легко расширять и добавлять свои собственные панели.
-- [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.
-- официальный [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, чтобы упростить процесс написания запросов и их выполнения. Это не ORM.
-- официальный [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для легкого извлечения и хранения данных в вашей базе данных.
+- official [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, которая помогает упростить процесс написания запросов и их выполнения. Это не ORM.
+- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper ActiveRecord Flight. Отличная небольшая библиотека для легкого извлечения и хранения данных в вашей базе данных.
- [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) - Простая очередь заданий - это библиотека, которая может быть использована для обработки заданий асинхронно. Она может быть использована с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL.
+- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Простая очередь заданий — это библиотека, которую можно использовать для асинхронной обработки заданий. Она может использоваться с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL.
## Сессия
Сессии не очень полезны для API, но для создания веб-приложения сессии могут быть решающими для поддержания состояния и информации о входе.
-- официальный [flightphp/session](/awesome-plugins/session) - Официальная библиотека сессий Flight. Это простая библиотека сессий, которая может использоваться для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (некоммутируемый, флеш, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии.
+- official [flightphp/session](/awesome-plugins/session) - Официальная библиотека сессий Flight. Это простая библиотека сессий, которая может использоваться для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (не блокирующий, всплывающий, сегментированный, шифрование сессий). Использует PHP open_ssl для необязательного шифрования/расшифрования данных сессии.
-## Шаблонизация
+## Шаблоны
-Шаблонизация является основой любого веб-приложения с пользовательским интерфейсом. Существует несколько движков шаблонизации, которые могут быть использованы с Flight.
+Шаблоны являются основой любого веб-приложения с пользовательским интерфейсом. Существует множество шаблонных двигателей, которые можно использовать с 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. Его также очень легко расширять и добавлять свои собственные фильтры и функции.
-## Участие
+## Вклад
-Есть плагин, которым вы хотели бы поделиться? Отправьте запрос на внесение изменений, чтобы добавить его в список!
\ No newline at end of file
+Есть плагин, которым вы хотели бы поделиться? Отправьте запрос на изменение, чтобы добавить его в список!
\ No newline at end of file
diff --git a/content/v3/ru/awesome-plugins/tracy_extensions.md b/content/v3/ru/awesome-plugins/tracy_extensions.md
index cfd5cf1..e157718 100644
--- a/content/v3/ru/awesome-plugins/tracy_extensions.md
+++ b/content/v3/ru/awesome-plugins/tracy_extensions.md
@@ -1,32 +1,32 @@
-Tracy Flight Panel Extensions
+Tracy Flight Панель Расширения
=====
-Это набор расширений, чтобы работа с Flight была немного более обширной.
+Это набор расширений, чтобы сделать работу с Flight немного более насыщенной.
-- Flight - Анализ всех переменных Flight.
-- Database - Анализ всех запросов, выполняемых на странице (если правильно инициировать соединение с базой данных).
-- Request - Анализ всех переменных `$_SERVER` и изучение всех глобальных нагрузок (`$_GET`, `$_POST`, `$_FILES`).
-- Session - Анализ всех переменных `$_SESSION`, если сеансы активны.
+- Flight - Анализировать все переменные Flight.
+- Database - Анализировать все запросы, которые были выполнены на странице (если вы правильно инициируете подключение к базе данных)
+- Request - Анализировать все переменные `$_SERVER` и examine все глобальные нагрузки (`$_GET`, `$_POST`, `$_FILES`)
+- Session - Анализировать все переменные `$_SESSION`, если сессии активны.
Это Панель
-
+
И каждая панель отображает очень полезную информацию о вашем приложении!
-
-
-
+
+
+
-Нажмите [здесь](https://github.com/flightphp/tracy-extensions), чтобы просмотреть код.
+Нажмите [здесь](https://github.com/flightphp/tracy-extensions), чтобы посмотреть код.
Установка
-------
-Запустите `composer require flightphp/tracy-extensions --dev` и вы на правильном пути!
+Запустите `composer require flightphp/tracy-extensions --dev`, и вы на пути!
Конфигурация
-------
-Вам нужно сделать очень небольшую настройку, чтобы начать использовать это. Вам нужно инициировать отладчик Tracy перед использованием этого [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Есть очень мало конфигураций, которые вам нужно выполнить, чтобы начать. Вам нужно будет инициировать отладчик Tracy перед использованием этого [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // Это должно быть false, иначе Tracy не сможет отображаться :(
+ // Это должно быть ложным, иначе Tracy не сможет рендерить :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -88,7 +89,7 @@ Flight::start();
### Latte
-Если у вас установлен Latte в вашем проекте, вы можете использовать панель Latte для анализа ваших шаблонов. Вы можете передать экземпляр Latte в конструктор `TracyExtensionLoader` с ключом `latte` вторым параметром.
+Если у вас установлен Latte в вашем проекте, вы можете использовать панель Latte для анализа ваших шаблонов. Вы можете передать экземпляр Latte в конструктор `TracyExtensionLoader` с помощью ключа `latte` во втором параметре.
```php
@@ -101,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // здесь вы добавляете Панель Latte в Tracy
+ // здесь вы добавляете панель Latte в Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // Это должно быть false, иначе Tracy не сможет отображаться :(
+ // Это должно быть ложным, иначе Tracy не сможет рендерить :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/ru/learn/events.md b/content/v3/ru/learn/events.md
index 56edafd..ca0a8e2 100644
--- a/content/v3/ru/learn/events.md
+++ b/content/v3/ru/learn/events.md
@@ -1,41 +1,41 @@
# Система событий в Flight PHP (v3.15.0+)
-Flight PHP вводит легкую и интуитивную систему событий, которая позволяет вам регистрировать и запускать пользовательские события в вашем приложении. С добавлением `Flight::onEvent()` и `Flight::triggerEvent()` вы теперь можете подключаться к ключевым моментам жизненного цикла вашего приложения или определять собственные события, чтобы сделать ваш код более модульным и расширяемым. Эти методы являются частью **настраиваемых методов** Flight, что означает, что вы можете переопределить их поведение в соответствии с вашими потребностями.
+Flight PHP вводит легкую и интуитивно понятную систему событий, которая позволяет вам регистрировать и вызывать пользовательские события в вашем приложении. С добавлением `Flight::onEvent()` и `Flight::triggerEvent()` вы теперь можете подключаться к ключевым моментам жизненного цикла вашего приложения или определять свои собственные события, чтобы сделать ваш код более модульным и расширяемым. Эти методы являются частью **картиируемых методов** Flight, что означает, что вы можете переопределить их поведение в соответствии с вашими потребностями.
-В этом руководстве приведено все, что вам нужно знать, чтобы начать работу с событиями, включая причины их ценности, как их использовать и практические примеры, которые помогут новичкам понять их мощь.
+Этот гид охватывает все, что вам нужно знать, чтобы начать работать с событиями, включая причины их ценности, как их использовать и практические примеры, помогающие новичкам понять их мощь.
-## Почему использовать события?
+## Зачем использовать события?
-События позволяют вам разделить различные части вашего приложения так, чтобы они не зависели слишком сильно друг от друга. Это разделение, часто называемое **разделением**, упрощает обновление, расширение или отладку вашего кода. Вместо того чтобы писать все в одном большом фрагменте, вы можете разделить свою логику на более мелкие, независимые части, которые реагируют на определенные действия (события).
+События позволяют вам разделить разные части вашего приложения так, чтобы они не зависели друг от друга слишком сильно. Это разделение, часто называемое **развязкой**, делает ваш код более простым в обновлении, расширении или отладке. Вместо того, чтобы писать все в одном большом куске, вы можете разделить вашу логику на более мелкие, независимые части, которые реагируют на конкретные действия (события).
-Представьте, что вы создаете приложение для блога:
-- Когда пользователь оставляет комментарий, вы можете захотеть:
+Представьте, что вы строите блог-приложение:
+- Когда пользователь публикует комментарий, вы можете захотеть:
- Сохранить комментарий в базе данных.
- Отправить электронное письмо владельцу блога.
- - Зафиксировать действие для безопасности.
+ - Записать действие для безопасности.
-Без событий вы бы напихали все это в одну функцию. С происшествиями вы можете разделить это: одна часть сохраняет комментарий, другая запускает событие типа `'comment.posted'`, а отдельные слушатели обрабатывают электронную почту и ведение журналов. Это делает ваш код более чистым и позволяет добавлять или удалять функции (например, уведомления), не трогая основную логику.
+Без событий вы бы запихнули все это в одну функцию. С событиями вы можете разделить это: одна часть сохраняет комментарий, другая инициирует событие, такое как `'comment.posted'`, а отдельные слушатели обрабатывают отправку электронного письма и ведение журнала. Это делает ваш код чище и позволяет вам добавлять или удалять функции (например, уведомления) без обращения к основной логике.
-### Обычные применения
-- **Ведение журнала**: Записывайте действия, такие как вход в систему или ошибки, без загромождения основного кода.
+### Общие применения
+- **Ведение журнала**: Записывайте действия, такие как входы или ошибки, не перегружая ваш основной код.
- **Уведомления**: Отправляйте электронные письма или оповещения, когда что-то происходит.
-- **Обновления**: Обновляйте кеши или уведомляйте другие системы о изменениях.
+- **Обновления**: Обновляйте кэши или уведомляйте другие системы о изменениях.
## Регистрация слушателей событий
-Чтобы прослушивать событие, используйте `Flight::onEvent()`. Этот метод позволяет вам определить, что должно произойти, когда событие происходит.
+Чтобы прослушивать событие, используйте `Flight::onEvent()`. Этот метод позволяет вам определить, что должно произойти, когда событие срабатывает.
### Синтаксис
```php
Flight::onEvent(string $event, callable $callback): void
```
- `$event`: Имя вашего события (например, `'user.login'`).
-- `$callback`: Функция, которая будет запущена, когда событие будет вызвано.
+- `$callback`: Функция, которая будет запущена при срабатывании события.
### Как это работает
-Вы "подписываетесь" на событие, сообщая Flight, что делать, когда оно происходит. Коллбек может принимать аргументы, переданные из триггера события.
+Вы "подписываетесь" на событие, сообщая Flight, что делать, когда оно происходит. Колбек может принимать аргументы, переданные от инициатора события.
-Система событий Flight является синхронной, что означает, что каждый слушатель события выполняется последовательно, один за другим. Когда вы инициируете событие, все зарегистрированные слушатели для этого события будут выполнены до завершения, прежде чем ваш код продолжит работу. Это важно понимать, так как это отличается от асинхронных систем событий, где слушатели могут работать параллельно или в более позднее время.
+Система событий Flight является синхронной, что означает, что каждый слушатель события выполняется в последовательности, один за другим. Когда вы инициируете событие, все зарегистрированные слушатели этого события будут выполнены до завершения, прежде чем ваш код продолжится. Это важно понимать, так как это отличается от асинхронных систем событий, где слушатели могут выполняться параллельно или в более позднее время.
### Простой пример
```php
@@ -43,21 +43,21 @@ Flight::onEvent('user.login', function ($username) {
echo "Добро пожаловать обратно, $username!";
});
```
-Здесь, когда событие `'user.login'` инициируется, оно поприветствует пользователя по имени.
+В этом примере, когда событие `'user.login'` будет инициировано, оно поприветствует пользователя по имени.
### Ключевые моменты
-- Вы можете добавить несколько слушателей к одному и тому же событию — они будут работать в порядке, в котором вы их зарегистрировали.
-- Коллбек может быть функцией, анонимной функцией или методом класса.
+- Вы можете добавить несколько слушателей к одному и тому же событию — они будут выполняться в порядке вашей регистрации.
+- Колбек может быть функцией, анонимной функцией или методом из класса.
-## Инициация событий
+## Инициирование событий
-Чтобы событие произошло, используйте `Flight::triggerEvent()`. Это сообщает Flight выполнить всех слушателей, зарегистрированных для этого события, передавая любые данные, которые вы предоставляете.
+Чтобы инициировать событие, используйте `Flight::triggerEvent()`. Это говорит Flight выполнить все слушатели, зарегистрированные для этого события, передавая любые данные, которые вы предоставляете.
### Синтаксис
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: Имя события, которое вы инициируете (должно соответствовать зарегистрированному событию).
+- `$event`: Имя события, которое вы инициируете (должно совпадать с зарегистрированным событием).
- `...$args`: Необязательные аргументы для передачи слушателям (может быть любое количество аргументов).
### Простой пример
@@ -65,58 +65,58 @@ Flight::triggerEvent(string $event, ...$args): void
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Это инициирует событие `'user.login'` и отправляет `'alice'` слушателю, который мы определили ранее, что приведет к выводу: `Добро пожаловать обратно, alice!`.
+Это инициирует событие `'user.login'` и отправляет `'alice'` слушателю, который мы определили ранее, который выведет: `Добро пожаловать обратно, alice!`.
### Ключевые моменты
-- Если слушатели не зарегистрированы, ничего не произойдет — ваше приложение не сломается.
-- Используйте оператор распространения (`...`), чтобы гибко передавать несколько аргументов.
+- Если не зарегистрированы слушатели, ничего не происходит — ваше приложение не сломается.
+- Используйте оператор распаковки (`...`), чтобы гибко передавать несколько аргументов.
### Регистрация слушателей событий
...
**Остановка дальнейших слушателей**:
-Если слушатель возвращает `false`, никакие дополнительные слушатели для этого события выполняться не будут. Это позволяет вам остановить цепочку событий на основе определенных условий. Помните, что порядок слушателей имеет значение, поскольку первый, кто вернет `false`, остановит последующих от работы.
+Если слушатель возвращает `false`, то никакие дополнительные слушатели для этого события не будут выполнены. Это позволяет вам остановить цепочку событий на основе специфических условий. Помните, что порядок слушателей важен, так как первый, кто вернет `false`, остановит выполнение остальных.
**Пример**:
```php
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
- return false; // Останавливает последующих слушателей
+ return false; // Останавливает последующие слушатели
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // это никогда не отправляется
+ sendWelcomeEmail($username); // это никогда не будет отправлено
});
```
## Переопределение методов событий
-`Flight::onEvent()` и `Flight::triggerEvent()` доступны для [расширения](/learn/extending), что означает, что вы можете перес définir, как они работают. Это прекрасно для продвинутых пользователей, которые хотят настроить систему событий, например, добавив ведение журнала или изменив, как события отправляются.
+`Flight::onEvent()` и `Flight::triggerEvent()` могут быть [расширены](/learn/extending), что позволяет вам переопределить, как они работают. Это отлично подходит для опытных пользователей, которые хотят настроить систему событий, например, добавляя ведение журнала или изменяя способ отправки событий.
### Пример: Настройка `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // Записывать каждую регистрацию события
- error_log("Добавлен новый слушатель события для: $event");
- // Вызвать стандартное поведение (предполагая наличие внутренней системы событий)
+ // Вести учет каждой регистрации события
+ error_log("Добавлен новый слушатель событий для: $event");
+ // Вызвать стандартное поведение (предполагая внутреннюю систему событий)
Flight::_onEvent($event, $callback);
});
```
-Теперь каждый раз, когда вы регистрируете событие, оно записывается перед продолжением.
+Теперь каждый раз, когда вы регистрируете событие, оно будет логироваться перед продолжением.
-### Почему переопределять?
+### Зачем переопределять?
- Добавить отладку или мониторинг.
- Ограничить события в определенных средах (например, отключить в тестировании).
-- Интеграция с другой библиотекой событий.
+- Интегрировать с другой библиотекой событий.
-## Куда поместить ваши события
+## Где размещать ваши события
-Как новичок, вы можете задаться вопросом: *где мне регистрировать все эти события в моем приложении?* Простота Flight означает, что нет строгого правила — вы можете разместить их там, где это имеет смысл для вашего проекта. Тем не менее, поддержание их организованными помогает вам поддерживать код по мере роста вашего приложения. Вот некоторые практические варианты и лучшие практики, адаптированные к легковесной природе Flight:
+Как новичку, вам может быть интересно: *где регистрировать все эти события в моем приложении?* Простота Flight означает, что нет строгого правила — вы можете размещать их везде, где это имеет смысл для вашего проекта. Однако их организацией помогает вам поддерживать код в порядке, по мере роста вашего приложения. Вот несколько практических вариантов и лучшие практики, адаптированные к легковесной природе Flight:
-### Вариант 1: В вашем основном `index.php`
-Для небольших приложений или быстрых прототипов вы можете зарегистрировать события прямо в вашем файле `index.php` наряду с вашими маршрутами. Это держит все в одном месте, что допустимо, когда простота является вашим приоритетом.
+### Вариант 1: В вашем основном файле `index.php`
+Для небольших приложений или быстрых прототипов вы можете регистрировать события прямо в вашем файле `index.php`, наряду с вашими маршрутами. Это позволяет держать все в одном месте, что вполне приемлемо, когда простота является приоритетом.
```php
require 'vendor/autoload.php';
@@ -130,16 +130,16 @@ Flight::onEvent('user.login', function ($username) {
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Вошли в систему!";
+ echo "Вошел в систему!";
});
Flight::start();
```
-- **Плюсы**: Просто, нет лишних файлов, отлично для маленьких проектов.
-- **Минусы**: Может стать беспорядочным, когда ваше приложение расширяется с большим количеством событий и маршрутов.
+- **Плюсы**: Просто, нет лишних файлов, отлично для небольших проектов.
+- **Минусы**: Может стать неаккуратным по мере роста вашего приложения с большим количеством событий и маршрутов.
### Вариант 2: Отдельный файл `events.php`
-Для несколько более крупного приложения подумайте о перемещении регистраций событий в специальный файл, такой как `app/config/events.php`. Включите этот файл в ваш `index.php` до ваших маршрутов. Это имитирует, как маршруты часто организованы в `app/config/routes.php` в проектах Flight.
+Для немного большего приложения рассмотрите возможность перемещения регистрации событий в отдельный файл, такой как `app/config/events.php`. Включите этот файл в ваш `index.php` перед маршрутами. Это имитирует, как маршруты часто организованы в `app/config/routes.php` в проектах Flight.
```php
// app/config/events.php
@@ -160,43 +160,43 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Вошли в систему!";
+ echo "Вошел в систему!";
});
Flight::start();
```
-- **Плюсы**: Держит `index.php` сосредоточенным на маршрутах, организует события логически, легко находить и редактировать.
-- **Минусы**: Добавляет небольшую структурированность, что может показаться излишним для очень маленьких приложений.
+- **Плюсы**: Держит `index.php` сосредоточенным на маршрутизации, логично организует события, легко находит и редактирует.
+- **Минусы**: Добавляет небольшой уровень структуры, который может показаться излишним для очень маленьких приложений.
-### Вариант 3: Ближе к месту их триггера
-Другой подход - регистрировать события рядом с тем, где они триггерятся, например, внутри контроллера или определения маршрута. Это хорошо работает, если событие специфично для одной части вашего приложения.
+### Вариант 3: Поблизости от места их срабатывания
+Другой подход — регистрировать события близко к тому месту, где они срабатывают, например, внутри контроллера или определения маршрута. Это хорошо работает, если событие специфично для одной части вашего приложения.
```php
Flight::route('/signup', function () {
- // Регистрация события здесь
+ // Зарегистрировать событие здесь
Flight::onEvent('user.registered', function ($email) {
- echo "Уведомление об приветствии отправлено на $email!";
+ echo "Отправлено приветственное письмо на $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Зарегистрировано!";
+ echo "Зарегистрировался!";
});
```
- **Плюсы**: Держит связанный код вместе, хорошо для изолированных функций.
-- **Минусы**: Рассекает регистрации событий, что усложняет возможности видеть все события сразу; риски дубликатов регистраций, если не быть осторожным.
+- **Минусы**: Разбрасывает регистрации событий, усложняя обзор всех событий; рискует дублировать регистрации, если не быть осторожным.
### Лучшие практики для Flight
-- **Начните с простого**: Для крошечных приложений размещайте события в `index.php`. Это быстро и соответствует минимализму Flight.
-- **Развивайтесь разумно**: По мере расширения вашего приложения (например, более 5-10 событий) используйте файл `app/config/events.php`. Это естественный шаг вверх, подобно организации маршрутов, и держит ваш код аккуратным без добавления сложных фреймворков.
-- **Избегайте чрезмерной инженерии**: Не создавайте полный «менеджер событий» или директорию, если ваше приложение не стало огромным — Flight процветает на простоте, поэтому держите его легким.
+- **Начните с простоты**: Для крошечных приложений помещайте события в `index.php`. Это быстро и соответствует минимализму Flight.
+- **Развивайтесь разумно**: По мере роста вашего приложения (например, более 5-10 событий) используйте файл `app/config/events.php`. Это естественный шаг вверх, как и организация маршрутов, и сохраняет ваш код аккуратным без добавления сложных фреймворков.
+- **Избегайте чрезмерного проектирования**: Не создавайте класс или каталог «менеджера событий» без особой нужды — Flight преуспевает в простоте, так что сохраняйте всё легковесным.
-### Советы: группировка по назначению
-В `events.php` группируйте связанные события (например, все события, связанные с пользователем, вместе) с комментариями для ясности:
+### Совет: Группируйте по цели
+В `events.php` группируйте связанные события (например, все события, связанные с пользователями, вместе) с комментариями для ясности:
```php
// app/config/events.php
-// События пользователя
+// События пользователей
Flight::onEvent('user.login', function ($username) {
error_log("$username вошел в систему");
});
@@ -204,44 +204,44 @@ Flight::onEvent('user.registered', function ($email) {
echo "Добро пожаловать на $email!";
});
-// События страницы
+// События страниц
Flight::onEvent('page.updated', function ($pageId) {
unset($_SESSION['pages'][$pageId]);
});
```
-Эта структура хорошо масштабируется и остается удобной для новичков.
+Эта структура хорошо масштабируется и остается дружелюбной для новичков.
## Примеры для новичков
Давайте рассмотрим несколько реальных сценариев, чтобы показать, как работают события и почему они полезны.
-### Пример 1: Ведение журнала входа пользователя
+### Пример 1: Ведение учета входа пользователя
```php
-// Шаг 1: Зарегистрируйте слушателя
+// Шаг 1: Зарегистрировать слушателя
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
error_log("$username вошел в систему в $time");
});
-// Шаг 2: Запустить это в вашем приложении
+// Шаг 2: Инициировать это в вашем приложении
Flight::route('/login', function () {
- $username = 'bob'; // Предположим, это из формы
+ $username = 'bob'; // Предположим, что это приходит из формы
Flight::triggerEvent('user.login', $username);
echo "Привет, $username!";
});
```
-**Почему это полезно**: Код входа не должен знать о ведении журнала — он просто инициирует событие. Позже вы можете добавить больше слушателей (например, отправить приветственное письмо) без изменения маршрута.
+**Почему это полезно**: Код входа не должен беспокоиться о ведении журнала — он просто инициирует событие. Позже вы можете добавить больше слушателей (например, отправить приветственное письмо) без изменения маршрута.
### Пример 2: Уведомление о новых пользователях
```php
// Слушатель для новых регистраций
Flight::onEvent('user.registered', function ($email, $name) {
- // Симулировать отправку письма
+ // Симуляция отправки электронного письма
echo "Электронное письмо отправлено на $email: Добро пожаловать, $name!";
});
-// Инициировать, когда кто-то подписывается
+// Инициировать это, когда кто-то зарегистрируется
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
@@ -249,41 +249,47 @@ Flight::route('/signup', function () {
echo "Спасибо за регистрацию!";
});
```
-**Почему это полезно**: Логика регистрации сосредоточена на создании пользователя, в то время как событие обрабатывает уведомления. Вы можете добавить другие слушатели (например, вести журнал регистрации) позже.
+**Почему это полезно**: Логика регистрации сосредоточена на создании пользователя, в то время как событие обрабатывает уведомления. Вы могли бы добавить больше слушателей (например, записывать регистрацию) позже.
-### Пример 3: Очистка кеша
+### Пример 3: Очистка кэша
```php
-// Слушатель для очистки кеша
+// Слушатель для очистки кэша
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Очистить сессионный кеш, если применимо
- echo "Кеш очищен для страницы $pageId.";
+ unset($_SESSION['pages'][$pageId]); // Очистить кэш сессии, если это применимо
+ echo "Кэш очищен для страницы $pageId.";
});
// Инициировать, когда страница редактируется
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Предположим, что мы обновили страницу
+ // Предположим, мы обновили страницу
Flight::triggerEvent('page.updated', $pageId);
echo "Страница $pageId обновлена.";
});
```
-**Почему это полезно**: Код редактирования не заботится о кешировании — он просто сигнализирует об обновлении. Другие части приложения могут реагировать по мере необходимости.
+**Почему это полезно**: Код редактирования не заботится о кэше — он просто сигнализирует о обновлении. Другие части приложения могут реагировать по мере необходимости.
## Лучшие практики
-- **Ясно именуйте события**: Используйте конкретные имена, такие как `'user.login'` или `'page.updated'`, чтобы было очевидно, что они делают.
-- **Держите слушателей простыми**: Не помещайте медленные или сложные задачи в слушателей — держите приложение быстрым.
-- **Тестируйте свои события**: Инициируйте их вручную, чтобы убедиться, что слушатели работают правильно.
-- **Используйте события разумно**: Они отличны для разделения, но слишком много может усложнить ваш код — используйте их, когда это имеет смысл.
+- **Ясно называйте события**: Используйте конкретные имена, такие как `'user.login'` или `'page.updated'`, чтобы было очевидно, что они делают.
+- **Держите слушателей простыми**: Не ставьте медленные или сложные задачи в слушателях — держите ваше приложение быстрым.
+- **Тестируйте ваши события**: Инициируйте их вручную, чтобы убедиться, что слушатели работают так, как ожидалось.
+- **Используйте события разумно**: Они отлично подходят для разъединения, но слишком много может сделать ваш код трудным для понимания — используйте их, когда это имеет смысл.
-Система событий в Flight PHP с `Flight::onEvent()` и `Flight::triggerEvent()` предоставляет вам простой, но мощный способ создания гибких приложений. Позволяя различным частям вашего приложения взаимодействовать друг с другом через события, вы можете держать код организованным, повторно используемым и простым в расширении. Будь то ведение журнала действий, отправка уведомлений или управление обновлениями, события помогают делать это, не запутывая вашу логику. Кроме того, с возможностью переопределения этих методов у вас есть свобода настраивать систему под ваши нужды. Начните с небольшого события и посмотрите, как это преобразует структуру вашего приложения!
+Система событий в Flight PHP с `Flight::onEvent()` и `Flight::triggerEvent()` предоставляет вам простой, но мощный способ создания гибких приложений. Позволяя различным частям вашего приложения взаимодействовать друг с другом через события, вы можете поддерживать свой код организованным, повторно используемым и легким для расширения. Будь то ведение журнала действий, отправка уведомлений или управление обновлениями, события помогают вам делать это без запутывания вашей логики. Плюс к этому, с возможностью переопределения этих методов у вас есть свобода настраивать систему под ваши нужды. Начните с небольшого события и наблюдайте, как это преобразует структуру вашего приложения!
## Встроенные события
-Flight PHP поставляется с несколькими встроенными событиями, которые вы можете использовать для подключения к жизненному циклу фреймворка. Эти события инициируются в определенные моменты в цикле запроса/ответа, что позволяет вам выполнять пользовательскую логику, когда происходят определенные действия.
+Flight PHP поставляется с несколькими встроенными событиями, которые вы можете использовать для подключения к жизненному циклу фреймворка. Эти события инициируются в конкретные моменты в цикле запроса/ответа, позволяя вам выполнять пользовательскую логику, когда происходят определенные действия.
### Список встроенных событий
-- `flight.request.received`: Инициируется, когда запрос принимается, обрабатывается и разбирается.
-- `flight.route.middleware.before`: Инициируется после выполнения промежуточного программного обеспечения до.
-- `flight.route.middleware.after`: Инициируется после выполнения промежуточного программного обеспечения после.
-- `flight.route.executed`: Инициируется после выполнения и обработки маршрута.
-- `flight.response.sent`: Инициируется после отправки ответа клиенту.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` Инициируется, когда запрос получен, распарсен и обработан.
+- **flight.error**: `function(Throwable $exception)` Инициируется, когда возникает ошибка в процессе обработки запроса.
+- **flight.redirect**: `function(string $url, int $status_code)` Инициируется, когда выполняется перенаправление.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Инициируется, когда кэш проверяется для конкретного ключа и если кэш попадает или нет.
+- **flight.middleware.before**: `function(Route $route)` Инициируется после выполнения промежуточного программного обеспечения перед ним.
+- **flight.middleware.after**: `function(Route $route)` Инициируется после выполнения промежуточного программного обеспечения после него.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Инициируется после выполнения любого промежуточного программного обеспечения.
+- **flight.route.matched**: `function(Route $route)` Инициируется, когда маршрут совпадает, но еще не выполнен.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Инициируется после выполнения и обработки маршрута. `$executionTime` — это время, затраченное на выполнение маршрута (вызов контроллера и т.д.).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Инициируется после рендеринга представления. `$executionTime` — это время, затраченное на рендеринг шаблона. **Примечание: Если вы переопределите метод `render`, вам нужно будет повторно инициировать это событие.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Инициируется после отправки ответа клиенту. `$executionTime` — это время, затраченное на создание ответа.
\ No newline at end of file
diff --git a/content/v3/uk/awesome-plugins/apm.md b/content/v3/uk/awesome-plugins/apm.md
new file mode 100644
index 0000000..6e4d708
--- /dev/null
+++ b/content/v3/uk/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM Документація
+
+Ласкаво просимо до FlightPHP APM—особистого тренера з продуктивності вашого додатку! Цей посібник є вашим дороговказом для налаштування, використання та освоєння Моніторингу Продуктивності Застосунків (APM) з FlightPHP. Незалежно від того, чи ви шукаєте повільні запити, чи просто хочете змоделювати графіки затримки, ми вас покриємо. Давайте зробимо ваш додаток швидшим, ваших користувачів щасливішими, а сеанси налагодження легшими!
+
+## Чому важливий APM
+
+Уявіть це: ваш додаток — це зайнятий ресторан. Без можливості відстежувати, як довго займають замовлення, або де кухня заважає, ви тільки гадатимете, чому клієнти йдуть незадоволеними. APM — це ваш су-шеф—він стежить за кожним кроком, від вхідних запитів до запитів до бази даних, та зазначає все, що уповільнює вас. Повільні сторінки втрачають користувачів (дослідження кажуть, що 53% йдуть, якщо сайт завантажується більше 3 секунд!), а APM допомагає вам виявити ці проблеми *до того, як* вони зашкодять. Це проактивний спокій—менше моментів «чому це не працює?», більше моментів «дивись, як це швидко працює!».
+
+## Встановлення
+
+Почніть з Composer:
+
+```bash
+composer require flightphp/apm
+```
+
+Вам потрібно:
+- **PHP 7.4+**: Підтримуємо LTS дистрибутиви Linux, при цьому підтримуючи сучасний PHP.
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легкий фреймворк, який ми покращуємо.
+
+## Початок роботи
+
+Ось ваш покроковий план до APM прекрасності:
+
+### 1. Зареєструйте APM
+
+Додайте це у ваш `index.php` або файл `services.php`, щоб почати відстеження:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**Що тут відбувається?**
+- `LoggerFactory::create()` отримує вашу конфігурацію (більше про це скоро) і налаштовує журнал—за замовчуванням SQLite.
+- `Apm` — це зірка—він слухає події Flight (запити, маршрути, помилки тощо) і збирає метрики.
+- `bindEventsToFlightInstance($app)` пов'язує все це з вашим додатком Flight.
+
+**Порада: Зразок**
+Якщо ваш додаток зайнятий, ведення журналістики *кожного* запиту може перевантажити систему. Використовуйте коефіцієнт вибірки (від 0.0 до 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // Журналює 10% запитів
+```
+
+Це дозволяє зберігати швидкість продуктивності, даючи вам при цьому надійні дані.
+
+### 2. Налаштуйте його
+
+Запустіть це, щоб створити ваш `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**Що це робить?**
+- Запускає майстра, який запитує, звідки беруться сирі метрики (джерело) і куди йдуть оброблені дані (призначення).
+- За замовчуванням—SQLite, наприклад, `sqlite:/tmp/apm_metrics.sqlite` для джерела, інше для призначення.
+- Ви отримаєте конфігурацію, як ця:
+ ```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"
+ }
+ }
+ ```
+
+**Чому два місця?**
+Сирі метрики накопичуються швидко (уявіть нефільтровані журнали). Робочий процес обробляє їх у структуроване призначення для інформаційної панелі. Зберігає порядок!
+
+### 3. Обробіть метрики за допомогою робітника
+
+Робітник перетворює сирі метрики на дані, готові до інформаційної панелі. Запустіть його один раз:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**Що він робить?**
+- Читає з вашого джерела (наприклад, `apm_metrics.sqlite`).
+- Обробляє до 100 метрик (рекомендований обсяг партії) до вашого призначення.
+- Зупиняється, коли закінчує або якщо не залишилося метрик.
+
+**Тримайте його запущеним**
+Для живих додатків вам знадобиться безперервна обробка. Ось варіанти:
+
+- **Режим демона**:
+ ```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`, щоб підключитися
+ ```
+ Зберігає його запущеним, навіть якщо ви виходите.
+
+- **Налаштування**:
+ ```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 хвилин.
+
+**Навіщо піклуватися?**
+Без робітника ваша інформаційна панель порожня. Це міст між сирими журналами та дієвими інсайтами.
+
+### 4. Запустіть інформаційну панель
+
+Подивіться на показники вашого додатку:
+
+```bash
+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.
+
+Натисніть на 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`
+
+#### Хочете іншу інформаційну панель?
+
+Ви можете побудувати свою власну інформаційну панель, якщо хочете! Подивіться на каталог vendor/flightphp/apm/src/apm/presenter, щоб отримати ідеї про те, як представляти дані для вашої власної інформаційної панелі!
+
+## Особливості інформаційної панелі
+
+Інформаційна панель є вашим APM головним офісом—ось що ви побачите:
+
+- **Журнал запитів**: Кожен запит з міткою часу, URL, кодом відповіді та загальним часом. Натисніть «Деталі», щоб побачити посередників, запити та помилки.
+- **Повільні запити**: Топ-5 запитів, що займають найбільше часу (наприклад, «/api/heavy» за 2.5с).
+- **Повільні маршрути**: Топ-5 маршрутів за середнім часом—чудово для виявлення шаблонів.
+- **Рівень помилок**: Відсоток запитів, що не виконуються (наприклад, 2.3% 500s).
+- **Перцентилі затримки**: 95-й (p95) та 99-й (p99) часи відповіді—знайте свої найгірші сценарії.
+- **Графік кодів відповіді**: Візуалізує 200s, 404s, 500s з часом.
+- **Довгі запити/Посередники**: Топ-5 повільних запитів до бази даних та рівнів посередників.
+- **Попадання/Пропуск кешу**: Як часто ваш кеш рятує ситуацію.
+
+**Додатково**:
+- Фільтруйте за «Остання година», «Останній день» або «Останній тиждень».
+- Перемикайте темний режим для тих запізнілих сеансів.
+
+**Приклад**:
+Запит до `/users` може показати:
+- Загальний час: 150мс
+- Посередник: `AuthMiddleware->handle` (50мс)
+- Запит: `SELECT * FROM users` (80мс)
+- Кеш: Попадання на `user_list` (5мс)
+
+## Додавання користувальницьких подій
+
+Відстежуйте що завгодно—наприклад, виклик API чи процес оплати:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**Де це з'являється?**
+У деталях запиту на інформаційній панелі під «Користувацькими подіями» — розширюване за допомогою красивого JSON-форматування.
+
+**Використання**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+Тепер ви зможете бачити, чи не тягне цей API ваш додаток вниз!
+
+## Моніторинг бази даних
+
+Відстежуйте запити PDO ось так:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**Що ви отримуєте**:
+- Текст запиту (наприклад, `SELECT * FROM users WHERE id = ?`)
+- Час виконання (наприклад, 0.015с)
+- Кількість рядків (наприклад, 42)
+
+**Зверніть увагу**:
+- **Необов’язково**: Пропустіть це, якщо вам не потрібно відстеження БД.
+- **Тільки PdoWrapper**: Основний PDO ще не підключено—чекайте на це!
+- **Попередження про продуктивність**: Ведення журналу кожного запиту на БД-насиченому сайті може сповільнити його. Використовуйте зразки (`$Apm = new Apm($ApmLogger, 0.1)`), щоб зменшити навантаження.
+
+**Приклад виходу**:
+- Запит: `SELECT name FROM products WHERE price > 100`
+- Час: 0.023с
+- Рядків: 15
+
+## Опції Робітника
+
+Налаштуйте робітника на свій смак:
+
+- `--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 метрик за раз.
+
+## Випадок проблем
+
+Ви застрягли? Спробуйте ці:
+
+- **Немає даних на інформаційній панелі?**
+ - Чи працює робітник? Перевірте `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 на стекові трасування.
+
+- **Інформаційна панель не запускається?**
+ - Порт 8001 зайнято? Використовуйте `--port 8080`.
+ - PHP не знайдено? Використовуйте `--php-path /usr/bin/php`.
+ - Брандмауер блокує? Відкрийте порт або використовуйте `--host localhost`.
+
+- **Занадто повільно?**
+ - Знизьте коефіцієнт вибірки: `$Apm = new Apm($ApmLogger, 0.05)` (5%).
+ - Зменшіть обсяг партії: `--batch_size 20`.
\ 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 462c4f4..508acfd 100644
--- a/content/v3/uk/awesome-plugins/awesome_plugins.md
+++ b/content/v3/uk/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
# Чудові плагіни
-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 в першу чергу.
-- [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 Spec з FlightPHP для побудови вашого API з використанням підходу "API перш за все".
+- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — це чудовий інструмент, який допоможе вам створити документацію API для ваших проектів Flight. Його дуже просто використовувати, і його можна налаштувати відповідно до ваших потреб. Це бібліотека PHP для створення документації Swagger.
+
+## Моніторинг продуктивності програми (APM)
+
+Моніторинг продуктивності програми (APM) є критично важливим для будь-якої програми. Він допомагає вам зрозуміти, як працює ваша програма і де знаходяться вузькі місця. Існує кілька інструментів APM, які можна використовувати з Flight.
+- бета[flightphp/apm](/awesome-plugins/apm) - Flight APM — це проста бібліотека APM, яка може використовуватися для моніторингу ваших програм Flight. Її можна використовувати для моніторингу продуктивності вашої програми та допомоги в ідентифікації вузьких місць.
## Аутентифікація/Авторизація
-Аутентифікація та авторизація є критично важливими для будь-якої програми, яка вимагає контролю за тим, хто може отримувати доступ до чого.
+Аутентифікація та авторизація є критично важливими для будь-якої програми, яка вимагає контролю доступу до певних ресурсів.
-- офіційний [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека дозволів Flight. Ця бібліотека є простим способом додавання дозволів на рівні користувача та програми до вашого застосунку.
+- офіційний [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека прав доступу Flight. Ця бібліотека є простим способом додати рівні прав доступу для користувачів та програм до вашої програми.
## Кешування
-Кешування - це чудовий спосіб пришвидшити вашу програму. Існує кілька бібліотек кешування, які можна використовувати з Flight.
+Кешування є чудовим способом прискорення вашої програми. Існує кілька бібліотек кешування, які можна використовувати з Flight.
-- офіційний [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста і незалежна клас для кешування на PHP.
+- офіційний [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна клас кешування PHP у файлі
## CLI
-CLI-додатки - це чудовий спосіб взаємодіяти з вашим додатком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів тощо.
+CLI-додатки є чудовим способом взаємодії з вашою програмою. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів і багато іншого.
-- офіційний [flightphp/runway](/awesome-plugins/runway) - Runway - це CLI-додаток, який допомагає вам управляти вашими додатками Flight.
+- офіційний [flightphp/runway](/awesome-plugins/runway) - Runway — це CLI-додаток, який допомагає вам керувати вашими програмами Flight.
-## Cookies
+## Куки
-Cookies - це чудовий спосіб зберігати невелику кількість даних на стороні клієнта. Їх можна використовувати для зберігання налаштувань користувача, налаштувань програми тощо.
+Куки — це чудовий спосіб зберігати невелику кількість даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань програми тощо.
-- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie - це бібліотека PHP, яка надає простий та ефективний спосіб керування cookie.
+- [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. Він має кілька панелей, які можуть допомогти вам налагодити вашу програму. Його також дуже легко розширити та додати свої власні панелі.
+- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовуючи [Tracy](/awesome-plugins/tracy) для обробки помилок, цей плагін додає кілька додаткових панелей, щоб допомогти з налагодженням спеціально для проектів Flight.
## Бази даних
-Бази даних є основою більшості додатків. Ось як ви зберігаєте та отримуєте дані. Деякі бібліотеки бази даних є просто обгортками для написання запитів, а інші є повнофункціональними ORM.
+Бази даних є основою більшості програм. Це те, як ви зберігаєте і отримуєте дані. Деякі бібліотеки баз даних є простими обгортками для написання запитів, а деякі є повноцінними ORM.
-- офіційний [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Офіційна обгортка Flight PDO, яка є частиною ядра. Це проста обгортка, яка допомагає спростити процес написання запитів та їх виконання. Це не є ORM.
-- офіційний [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ActiveRecord ORM/Mapper Flight. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних.
-- [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту.
+- офіційний [flightphp/core PdoWrapper](/awesome-plugins/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) - Це бібліотека, яку можна використовувати для шифрування та дешифрування даних. Розпочати досить просто, щоб розпочати шифрування та дешифрування даних.
-## Черга завдань
+## Робочий черга
-Черги завдань дуже корисні для асинхронної обробки завдань. Це може бути відправка електронних листів, обробка зображень або що завгодно, що не потрібно виконувати в реальному часі.
+Робочі черги дуже корисні для асинхронної обробки завдань. Це може бути надсилання електронних листів, обробка зображень або будь-що, що не потрібно виконувати в реальному часі.
-- [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. Це проста бібліотека сесій, яку можна використовувати для зберігання та отримання даних сесії. Вона використовує вбудовану обробку сесій PHP.
-- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сесій PHP (не блокуючий, спалах, сегмент, шифрування сесій). Використовує PHP open_ssl для необов'язкового шифрування/дешифрування даних сесії.
+- офіційний [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека сесій Flight. Це проста бібліотека сесій, яку можна використовувати для зберігання та отримання даних сесій. Вона використовує вбудовану обробку сесій PHP.
+- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сесій PHP (неблокуючий, флеш, сегмент, шифрування сесій). Використовує PHP open_ssl для можливого шифрування/дешифрування даних сесій.
-## Шаблонізація
+## Темплейтинг
-Шаблонізація є основою будь-якого веб-додатку з інтерфейсом. Існує кілька движків шаблонізації, які можна використовувати з Flight.
+Темплейтинг є основою будь-якого веб-додатку з інтерфейсом. Існує кілька механізмів темплейтингу, які можна використовувати з Flight.
-- застарілий [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. Також дуже легко розширити і додати свої фільтри та функції.
-## Участь
+## Внесення внесків
-Є плагін, яким ви хочете поділитися? Надішліть запит на злиття, щоб додати його до списку!
\ No newline at end of file
+Маєте плагін, яким хочете поділитись? Надішліть запит на злиття, щоб додати його до списку!
\ No newline at end of file
diff --git a/content/v3/uk/awesome-plugins/tracy_extensions.md b/content/v3/uk/awesome-plugins/tracy_extensions.md
index 2bb4e21..09b1efb 100644
--- a/content/v3/uk/awesome-plugins/tracy_extensions.md
+++ b/content/v3/uk/awesome-plugins/tracy_extensions.md
@@ -1,18 +1,18 @@
Tracy Flight Panel Extensions
=====
-Це набір розширень, щоб зробити роботу з Flight трохи більш насиченою.
+Це набір розширень для покращення роботи з Flight.
- Flight - Аналізувати всі змінні Flight.
-- Database - Аналізувати всі запити, що виконалися на сторінці (якщо ви правильно ініціювали з'єднання з базою даних)
+- Database - Аналізувати всі запити, які виконувалися на сторінці (якщо ви правильно ініціювали підключення до бази даних)
- Request - Аналізувати всі змінні `$_SERVER` та перевіряти всі глобальні дані (`$_GET`, `$_POST`, `$_FILES`)
-- Session - Аналізувати всі змінні `$_SESSION`, якщо сесії активно використовуються.
+- Session - Аналізувати всі змінні `$_SESSION`, якщо сесії активні.
Це панель

-І кожна панель показує дуже корисну інформацію про вашу програму!
+І кожна панель відображає дуже корисну інформацію про ваш додаток!


@@ -20,13 +20,13 @@ Tracy Flight Panel Extensions
Натисніть [тут](https://github.com/flightphp/tracy-extensions), щоб переглянути код.
-Installation
+Встановлення
-------
-Запустіть `composer require flightphp/tracy-extensions --dev` і ви на правильному шляху!
+Запустіть `composer require flightphp/tracy-extensions --dev`, і ви на правильному шляху!
-Configuration
+Налаштування
-------
-Є дуже небагато конфігурацій, які вам потрібно зробити, щоб це запрацювало. Вам потрібно ініціювати відладчик Tracy перед використанням цього [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+Існує дуже мало налаштувань, які потрібно зробити, щоб це запрацювало. Вам потрібно ініціювати відлагоджувач Tracy перед використанням цього [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // Це повинно бути false або Tracy не зможе відобразити :(
+ // Це має бути false, інакше Tracy не зможе його відобразити :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
@@ -101,12 +102,12 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // це те місце, де ви додаєте панель Latte до Tracy
+ // це місце, де ви додаєте панель Latte до Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // Це повинно бути false або Tracy не зможе відобразити :(
+ // Це має бути false, інакше Tracy не зможе його відобразити :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
diff --git a/content/v3/uk/learn/events.md b/content/v3/uk/learn/events.md
index 7848100..991c12b 100644
--- a/content/v3/uk/learn/events.md
+++ b/content/v3/uk/learn/events.md
@@ -1,41 +1,41 @@
# Система подій у Flight PHP (v3.15.0+)
-Flight PHP вводить легку та інтуїтивно зрозумілу систему подій, яка дозволяє вам реєструвати та активувати власні події у вашій програмі. З додаванням `Flight::onEvent()` та `Flight::triggerEvent()`, ви тепер можете підключатися до ключових моментів життєвого циклу вашого додатку або визначати свої власні події, щоб зробити ваш код більш модульним та розширювальним. Ці методи є частиною **відображуваних методів** Flight, що означає, що ви можете перевизначити їх поведінку відповідно до ваших потреб.
+Flight PHP впроваджує легку та інтуїтивно зрозумілу систему подій, яка дозволяє вам реєструвати та викликати користувацькі події у вашому додатку. Завдяки додаванню `Flight::onEvent()` та `Flight::triggerEvent()`, ви тепер можете підключатися до ключових моментів життєвого циклу вашого додатка або визначати власні події, щоб робити ваш код більш модульним та розширюваним. Ці методи є частиною **мапованих методів** Flight, що означає, що ви можете переопределити їхню поведінку відповідно до ваших потреб.
-Цей посібник охоплює все, що вам потрібно знати, щоб почати працювати з подіями, включаючи чому вони цінні, як їх використовувати та практичні приклади, щоб допомогти новачкам зрозуміти їхню силу.
+Цей посібник охоплює все, що вам потрібно знати для початку роботи з подіями, включаючи те, чому вони мають цінність, як їх використовувати та практичні приклади, які допоможуть новачкам зрозуміти їхню силу.
## Чому варто використовувати події?
-Події дозволяють вам розділити різні частини вашого додатку так, щоб вони не залежали занадто сильно один від одного. Це розділення — часто називане **декуплінгом** — робить ваш код легшим для оновлення, розширення чи налагодження. Замість того, щоб писати все в одному великому шматку, ви можете розділити вашу логіку на менші, незалежні частини, які реагують на конкретні дії (події).
+Події дозволяють вам розділити різні частини вашого додатка так, щоб вони не залежали одна від одної занадто сильно. Це розділення, яке часто називають **декуплюванням**, полегшує оновлення, розширення або налагодження вашого коду. Замість того, щоб писати все в одному великому блоці, ви можете розділити вашу логіку на менші, незалежні частини, які реагують на конкретні дії (події).
-Уявіть, що ви розробляєте додаток для блогу:
-- Коли користувач залишає коментар, ви можливо захочете:
+Уявіть, що ви створюєте блог додаток:
+- Коли користувач публікує коментар, ви можете захотіти:
- Зберегти коментар у базі даних.
- Відправити електронний лист власнику блогу.
- - Залоги приводу для безпеки.
+ - Залогувати дію для безпеки.
-Без подій, ви б змусили все це в одну функцію. З подіями, ви можете розділити це: одна частина зберігає коментар, інша активує подію на кшталт `'comment.posted'`, а окремі слухачі обробляють електронну пошту та логування. Це зберігає ваш код чистішим та дозволяє вам додавати або видаляти функції (як-от сповіщення) без втручання в основну логіку.
+Без подій ви були б змушені все це втиснути в одну функцію. З подіями ви можете розділити це: одна частина зберігає коментар, інша викликає подію, таку як `'comment.posted'`, а окремі слухачі обробляють електронну пошту та логування. Це робить ваш код чистішим і дозволяє додавати чи видаляти функції (такі як сповіщення) без втручання в основну логіку.
-### Загальні застосування
-- **Логування**: Записуйте дії, такі як входи або помилки, не заважаючи вашому основному коду.
+### Загальні використання
+- **Логування**: Записуйте дії, такі як входи або помилки, без заповнення вашого основного коду.
- **Сповіщення**: Відправляйте електронні листи або сповіщення, коли щось відбувається.
-- **Оновлення**: Оновлюйте кеш або сповіщайте інші системи про зміни.
+- **Оновлення**: Оновлюйте кеші або сповіщайте інші системи про зміни.
## Реєстрація слухачів подій
-Щоб прослухати подію, використовуйте `Flight::onEvent()`. Цей метод дозволяє вам визначити, що повинно відбутися, коли подія виникає.
+Щоб слухати подію, використовуйте `Flight::onEvent()`. Цей метод дозволяє вам визначити, що повинно відбутися, коли подія виникає.
### Синтаксис
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`: Назва вашої події (наприклад, `'user.login'`).
-- `$callback`: Функція, яка виконується, коли подія активується.
+- `$event`: Ім'я вашої події (наприклад, `'user.login'`).
+- `$callback`: Функція, яку потрібно виконати, коли подія викликається.
### Як це працює
-Ви "підписуєтеся" на подію, кажучи Flight, що робити, коли це відбувається. Колбек може приймати аргументи, передані з тригера події.
+Ви "підписуєтеся" на подію, кажучи Flight, що робити, коли це відбудеться. Колбек може приймати аргументи, передані з тригера події.
-Система подій Flight є синхронною, що означає, що кожен слухач подій виконується в послідовності, один за одним. Коли ви активуєте подію, всі зареєстровані слухачі для цієї події будуть виконані до завершення, перш ніж ваш код продовжиться. Це важливо розуміти, оскільки це відрізняється від асинхронних систем подій, де слухачі можуть виконуватись паралельно або в пізніший час.
+Система подій Flight є синхронною, що означає, що кожен слухач подій виконується послідовно, один за іншим. Коли ви викликаєте подію, всі зареєстровані слухачі для цієї події будуть запущені до завершення, перш ніж ваш код продовжить роботу. Це важливо зрозуміти, оскільки це відрізняється від асинхронних систем подій, де слухачі можуть виконуватися паралельно або в пізніший час.
### Простий приклад
```php
@@ -43,40 +43,40 @@ Flight::onEvent('user.login', function ($username) {
echo "Ласкаво просимо назад, $username!";
});
```
-Тут, коли активується подія `'user.login'`, вона привітає користувача за іменем.
+Тут, коли подія `'user.login'` викликається, вона привітає користувача за ім'ям.
-### Ключові моменти
-- Ви можете додати кілька слухачів до однієї й тієї ж події — вони виконуватимуться в порядку, в якому ви їх зареєстрували.
-- Колбек може бути функцією, анонімною функцією або методом класу.
+### Основні моменти
+- Ви можете додати кілька слухачів до однієї події — вони виконуватимуться в порядку їх реєстрації.
+- Колбек може бути функцією, анонімною функцією або методом з класу.
-## Активація подій
+## Виклик подій
-Щоб зробити подію активною, використовуйте `Flight::triggerEvent()`. Це говорить Flight виконати всіх слухачів, зареєстрованих для цієї події, передаючи будь-які дані, які ви надаєте.
+Щоб викликати подію, використовуйте `Flight::triggerEvent()`. Це говорить Flight виконати всі слухачі, зареєстровані для цієї події, передаючи будь-які дані, які ви надали.
### Синтаксис
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`: Назва події, яку ви активуєте (має відповідати зареєстрованій події).
-- `...$args`: Опціональні аргументи для відправки слухачам (може бути будь-яка кількість аргументів).
+- `$event`: Ім'я події, яку ви викликаєте (повинно відповідати зареєстрованій події).
+- `...$args`: Додаткові аргументи для передачі слухачам (може бути будь-яка кількість аргументів).
### Простий приклад
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-Це активує подію `'user.login'` і передає `'alice'` слухачу, якого ми визначили раніше, який виведе: `Ласкаво просимо назад, alice!`.
+Це викликає подію `'user.login'` і передає `'alice'` слухачеві, якого ми визначили раніше, який виведе: `Ласкаво просимо назад, alice!`.
-### Ключові моменти
-- Якщо не зареєстровано слухачів, нічого не відбувається — ваш додаток не буде ламатися.
-- Використовуйте оператор поширення (`...`), щоб гнучко передавати кілька аргументів.
+### Основні моменти
+- Якщо не зареєстровано слухачів, нічого не станеться — ваш додаток не зламається.
+- Використовуйте оператор розподілу (`...`), щоб гнучко передавати кілька аргументів.
### Реєстрація слухачів подій
...
**Зупинка подальших слухачів**:
-Якщо слухач повертає `false`, жоден з наступних слухачів для цієї події не буде виконано. Це дозволяє вам зупинити ланцюг подій на основі конкретних умов. Пам'ятайте, що порядок слухачів має значення, оскільки перший, хто повертає `false`, зупинить решту від виконання.
+Якщо слухач повертає `false`, жоден з наступних слухачів для цієї події не буде виконаний. Це дозволяє вам зупинити ланцюг подій на основі конкретних умов. Пам'ятайте, що порядок слухачів має значення, оскільки перший, хто повертає `false`, зупинить решту від виконання.
**Приклад**:
```php
@@ -87,15 +87,15 @@ Flight::onEvent('user.login', function ($username) {
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // цей ніколи не буде надіслано
+ sendWelcomeEmail($username); // цього ніколи не відправляється
});
```
-## Перевизначення методів подій
+## Переопределення методів подій
-`Flight::onEvent()` та `Flight::triggerEvent()` доступні для [розширення](/learn/extending), що означає, що ви можете переозначити, як вони працюють. Це чудово підходить для просунутих користувачів, які хочуть налаштувати систему подій, наприклад, додати логування або змінити, як події передаються.
+`Flight::onEvent()` та `Flight::triggerEvent()` доступні для [розширення](/learn/extending), що означає, що ви можете переопределити їхню роботу. Це чудово для просунутих користувачів, які хочуть налаштувати систему подій, наприклад, додати логування або змінити спосіб, яким події розсилаються.
-### Приклад: Налаштування `onEvent`
+### Приклад: Кастомізація `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
// Логувати кожну реєстрацію події
@@ -104,47 +104,47 @@ Flight::map('onEvent', function (string $event, callable $callback) {
Flight::_onEvent($event, $callback);
});
```
-Тепер кожного разу, коли ви реєструєте подію, вона записується перед продовженням.
+Тепер кожного разу, коли ви реєструєте подію, вона логуватим це перед тим, як продовжити.
### Чому перевизначати?
- Додати налагодження або моніторинг.
-- Обмежити події в певних середовищах (наприклад, вимкнути у тестуванні).
-- Інтегруватися з іншою бібліотекою подій.
+- Обмежити події в певних середовищах (наприклад, відключити в тестуванні).
+- Інтегрувати з іншою бібліотекою подій.
-## Де розмістити ваші події
+## Де реєструвати ваші події
-Як новачок, ви можете запитати: *де мені реєструвати всі ці події в моєму додатку?* Простота Flight означає, що немає суворих правил — ви можете помістити їх туди, де це має сенс для вашого проекту. Проте, збереження їх в організованому вигляді допоможе вам підтримувати ваш код в міру зростання вашого додатку. Ось кілька практичних варіантів і найкращих практик, адаптованих до легкості Flight:
+Як новачок, ви, можливо, будете запитувати: *де мені реєструвати всі ці події в моєму додатку?* Простота Flight означає, що немає строгих правил — ви можете розмістити їх де завгодно, що має сенс для вашого проекту. Однак організація допоможе вам підтримувати ваш код у міру зростання вашого додатку. Ось кілька практичних варіантів та найкращих практик, спеціально адаптованих до легкої природи Flight:
### Варіант 1: У вашому основному `index.php`
-Для невеликих додатків або швидких прототипів ви можете зареєструвати події прямо у вашому файлі `index.php`, поряд з вашими маршрутами. Це утримує все в одному місці, що є прийнятним, коли простота є вашим пріоритетом.
+Для невеликих додатків або швидких прототипів ви можете реєструвати події прямо у вашому файлі `index.php` поряд з вашими маршрутами. Це утримує все в одному місці, що добре, коли простота є вашим пріоритетом.
```php
require 'vendor/autoload.php';
// Реєстрація подій
Flight::onEvent('user.login', function ($username) {
- error_log("$username увійшов о " . date('Y-m-d H:i:s'));
+ error_log("$username увійшов в систему о " . date('Y-m-d H:i:s'));
});
// Визначення маршрутів
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Увійшов!";
+ echo "Увійшли!";
});
Flight::start();
```
-- **Плюси**: Просто, немає додаткових файлів, відмінно для невеликих проектів.
-- **Мінуси**: Може стати неохайно, коли ваш додаток зростає з більшими подіями та маршрутами.
+- **Плюси**: Просто, немає додаткових файлів, чудово для невеликих проектів.
+- **Мінуси**: Може стати заплутаним, коли ваш додаток розвивається з багатьма подіями та маршрутами.
### Варіант 2: Окремий файл `events.php`
-Для трохи більших додатків розгляньте можливість перенесення реєстрацій подій у спеціалізований файл, такий як `app/config/events.php`. Включіть цей файл у ваш `index.php` перед вашими маршрутами. Це імітує те, як маршрути часто організовані в `app/config/routes.php` у проектах Flight.
+Для трохи більшого додатку розгляньте можливість перемістити реєстрацію подій у спеціальний файл, наприклад `app/config/events.php`. Включіть цей файл у вашому `index.php` перед маршрутами. Це імітує організацію, якою часто користуються маршрути в `app/config/routes.php` у проектах Flight.
```php
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
- error_log("$username увійшов о " . date('Y-m-d H:i:s'));
+ error_log("$username увійшов в систему о " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
@@ -160,45 +160,45 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "Увійшов!";
+ echo "Увійшли!";
});
Flight::start();
```
-- **Плюси**: Зберігає `index.php` зосередженим на маршрутизації, логічно організовує події, легко знаходити та редагувати.
-- **Мінуси**: Додає трохи структури, що може відчуватися надмірно для дуже малих додатків.
+- **Плюси**: Зберігає `index.php` зосередженим на маршрутах, організовує події логічно, легко знайти та редагувати.
+- **Мінуси**: Додає трохи структури, що може відчуватися як зайве для дуже маленьких додатків.
-### Варіант 3: Поруч з місцем, де їх активують
-Ще один підхід - реєструвати події ближче до місця, де їх активують, наприклад, всередині контролера або визначення маршруту. Це добре працює, якщо подія специфічна для однієї частини вашого додатку.
+### Варіант 3: Біля тих, що їх викликають
+Ще один підхід — реєструвати події близько до того, де їх викликають, наприклад, всередині контролера або визначення маршруту. Це добре працює, якщо подія специфічна для однієї частини вашого додатку.
```php
Flight::route('/signup', function () {
- // Реєструвати подію тут
+ // Реєстрація події тут
Flight::onEvent('user.registered', function ($email) {
- echo "Сповіщення надіслано на $email!";
+ echo "Відправлено вітальний електронний лист на $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "Зареєстровано!";
+ echo "Зареєстровані!";
});
```
-- **Плюси**: Зберігає пов’язаний код разом, добре для ізольованих функцій.
-- **Мінуси**: Розкидає реєстрації подій, ускладнюючи перегляд усіх подій одночасно; ризик дублікатів реєстрацій, якщо не бути уважним.
+- **Плюси**: Тримає пов'язаний код разом, добре для ізольованих функцій.
+- **Мінуси**: Розсіює реєстрацію подій, ускладнюючи перегляд всіх подій одночасно; ризики повторних реєстрацій, якщо не бути обережним.
### Найкраща практика для Flight
-- **Починайте з простоти**: Для крихітних додатків розмістіть події в `index.php`. Це швидко і відповідає мінімалізму Flight.
-- **Розвивайтеся розумно**: Коли ваш додаток розширюється (наприклад, більше 5-10 подій), використовуйте файл `app/config/events.php`. Це природний крок уперед, як організація маршрутів, і утримує ваш код охайним без надмірного ускладнення.
-- **Уникайте надмірної інженерії**: Не створюйте повноцінний "клас менеджера подій" або каталог, якщо ваш додаток не став величезним — Flight процвітає завдяки простоті, тому зберігайте його легким.
+- **Почніть з простого**: Для маленьких додатків помістіть події в `index.php`. Це швидко і узгоджується з мінімалізмом Flight.
+- **Розвивайтеся розумно**: Коли ваш додаток зростає (наприклад, більше 5-10 подій), використовуйте файл `app/config/events.php`. Це природний крок уперед, подібно до організації маршрутів, і підтримує ваш код акуратним без додавання складних фреймворків.
+- **Уникайте надмірного інженерства**: Не створюйте повноцінний клас або директорію "менеджера подій", якщо ваш додаток не став величезним — Flight розвивається за простотою, тому тримайте його легким.
-### Порада: Групуйте за метою
-У `events.php`, групуйте пов’язані події (наприклад, всі події, пов’язані з користувачами, разом) з коментарями для чіткості:
+### Порада: Групуйте за призначенням
+У файлі `events.php` групуйте пов'язані події (наприклад, всі події, пов'язані з користувачами, разом) з коментарями для ясності:
```php
// app/config/events.php
// Події користувачів
Flight::onEvent('user.login', function ($username) {
- error_log("$username увійшов");
+ error_log("$username увійшов в систему");
});
Flight::onEvent('user.registered', function ($email) {
echo "Ласкаво просимо до $email!";
@@ -210,7 +210,7 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-Ця структура добре масштабується і залишається зрозумілою для новачків.
+Ця структура добре масштабується і залишається дружньою до новачків.
## Приклади для новачків
@@ -221,69 +221,75 @@ Flight::onEvent('page.updated', function ($pageId) {
// Крок 1: Реєстрація слухача
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
- error_log("$username увійшов о $time");
+ error_log("$username увійшов в систему о $time");
});
-// Крок 2: Активуйте це у вашому додатку
+// Крок 2: Виклик його у вашому додатку
Flight::route('/login', function () {
- $username = 'bob'; // Уявімо, що це приходить з форми
+ $username = 'bob'; // Припустимо, що це приходить з форми
Flight::triggerEvent('user.login', $username);
echo "Привіт, $username!";
});
```
-**Чому це корисно**: Код входу не повинен знати про логування — він просто активує подію. Ви можете пізніше додати більше слухачів (наприклад, відправити вітальний лист) без зміни маршруту.
+**Чому це корисно**: Код входу не повинен знати про логування — він просто викликає подію. Ви можете пізніше додати більше слухачів (наприклад, надіслати вітальний електронний лист) без зміни маршруту.
### Приклад 2: Сповіщення про нових користувачів
```php
// Слухач для нових реєстрацій
Flight::onEvent('user.registered', function ($email, $name) {
- // Імітувати відправлення електронного листа
+ // Симулювати відправлення електронного листа
echo "Електронний лист надіслано на $email: Ласкаво просимо, $name!";
});
-// Активуйте це, коли хтось реєструється
+// Виклик його, коли хтось підписується
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "Дякуємо за реєстрацію!";
+ echo "Дякуємо за підписку!";
});
```
-**Чому це корисно**: Логіка реєстрації зосереджена на створенні користувача, тоді як подія обробляє сповіщення. Ви могли б додати більше слухачів (наприклад, залогувати реєстрацію) пізніше.
+**Чому це корисно**: Логіка підписки фокусується на створенні користувача, тоді як подія обробляє сповіщення. Ви могли б додати більше слухачів (наприклад, логувати підписку) пізніше.
-### Приклад 3: Очистка кешу
+### Приклад 3: Очищення кешу
```php
// Слухач для очищення кешу
Flight::onEvent('page.updated', function ($pageId) {
- unset($_SESSION['pages'][$pageId]); // Очистити кеш сесії, якщо це доречно
+ unset($_SESSION['pages'][$pageId]); // Очистити кеш сесії, якщо це застосовно
echo "Кеш очищено для сторінки $pageId.";
});
-// Активуйте це, коли сторінка редагується
+// Виклик, коли сторінка редагується
Flight::route('/edit-page/(@id)', function ($pageId) {
- // Уявімо, що ми оновили сторінку
+ // Припустимо, що ми оновили сторінку
Flight::triggerEvent('page.updated', $pageId);
echo "Сторінка $pageId оновлена.";
});
```
-**Чому це корисно**: Код редагування не повинен піклуватися про кешування — він просто сигналізує про оновлення. Інші частини програми можуть реагувати на це за потребою.
+**Чому це корисно**: Код редагування не піклується про кешування — він просто сигналізує про оновлення. Інші частини програми можуть реагувати за потреби.
## Найкращі практики
-- **Чітко називайте події**: Використовуйте специфічні назви, такі як `'user.login'` або `'page.updated'`, щоб було очевидно, що вони роблять.
-- **Зберігайте слухачів простими**: Не ставте повільні або складні завдання в слухачах — зберігайте ваш додаток швидким.
-- **Тестуйте ваші події**: Активуйте їх вручну, щоб переконатися, що слухачі працюють, як очікується.
-- **Використовуйте події з розумом**: Вони чудово підходять для декуплінгу, але надто багато може ускладнити ваш код — використовуйте їх, коли це має сенс.
+- **Чітко називайте події**: Використовуйте специфічні назви, як `'user.login'` або `'page.updated'`, щоб було зрозуміло, що вони роблять.
+- **Зберігайте слухачів простими**: Не ставте повільні або складні завдання в слухачі — тримайте ваш додаток швидким.
+- **Тестуйте ваші події**: Викликайте їх вручну, щоб переконатися, що слухачі працюють, як очікувалося.
+- **Використовуйте події мудро**: Вони чудово підходять для декуплювання, але надто велика їх кількість може ускладнити ваш код — використовуйте їх, коли це має сенс.
-Система подій у Flight PHP, з `Flight::onEvent()` та `Flight::triggerEvent()`, дає вам простий, але потужний спосіб створювати гнучкі додатки. Дозволяючи різним частинам вашого додатку спілкуватися одне з одним через події, ви можете зберігати ваш код організованим, повторно використаним і легким для розширення. Чи ви логіруєте дії, надсилаєте сповіщення чи управляєте оновленнями, події допомагають вам робити це без заплутування вашої логіки. Більше того, з можливістю перевизначення цих методів, ви отримуєте свободу налаштувати систему під ваші потреби. Почніть з маленької події і спостерігайте, як вона трансформує структуру вашого додатку!
+Система подій у Flight PHP, з `Flight::onEvent()` та `Flight::triggerEvent()`, надає вам простий, але потужний спосіб створення гнучких додатків. Дозволяючи різним частинам вашого додатку спілкуватися одна з одною через події, ви можете зберегти свій код організованим, повторно використовуваним і легким для розширення. Незалежно від того, чи ви логгеруєте дії, надсилаєте сповіщення чи керуєте оновленнями, події допомагають вам робити це без заплутування вашої логіки. Крім того, з можливістю переопределення цих методів, у вас є свобода налаштувати систему відповідно до ваших потреб. Починайте з малого з однією подією і спостерігайте, як це трансформує структуру вашого додатку!
## Вбудовані події
-Flight PHP поставляється з кількома вбудованими подіями, які ви можете використовувати для підключення до життєвого циклу фреймворку. Ці події активуються в певні моменти в циклі запит/відповідь, дозволяючи вам виконувати власну логіку, коли відбуваються певні дії.
+Flight PHP постачає кілька вбудованих подій, які ви можете використовувати для підключення до життєвого циклу фреймворка. Ці події викликаються в певні моменти циклу запиту/відповіді, що дозволяє вам виконувати користувацьку логіку, коли трапляються певні дії.
### Список вбудованих подій
-- `flight.request.received`: Активується, коли запит отримано, розпарсено та оброблено.
-- `flight.route.middleware.before`: Активується, після того як виконано попереднє проміжне програмне забезпечення.
-- `flight.route.middleware.after`: Активується, після того як виконано післяпроміжне програмне забезпечення.
-- `flight.route.executed`: Активується після виконання та обробки маршруту.
-- `flight.response.sent`: Активується після того, як відповідь надіслана клієнту.
\ No newline at end of file
+- **flight.request.received**: `function(Request $request)` Викликається, коли запит отримано, проаналізовано та оброблено.
+- **flight.error**: `function(Throwable $exception)` Викликається, коли під час життєвого циклу запиту виникає помилка.
+- **flight.redirect**: `function(string $url, int $status_code)` Викликається, коли ініціюється перенаправлення.
+- **flight.cache.checked**: `function(string $cache_key, bool $hit, float $executionTime)` Викликається, коли кеш перевіряється для певного ключа та вказує, чи був кешований або пропущений.
+- **flight.middleware.before**: `function(Route $route)` Викликається після виконання перед середнього програмного забезпечення.
+- **flight.middleware.after**: `function(Route $route)` Викликається після виконання після середнього програмного забезпечення.
+- **flight.middleware.executed**: `function(Route $route, $middleware, string $method, float $executionTime)` Викликається після виконання будь-якого середнього програмного забезпечення.
+- **flight.route.matched**: `function(Route $route)` Викликається, коли маршрут співпадає, але ще не запускається.
+- **flight.route.executed**: `function(Route $route, float $executionTime)` Викликається після виконання та обробки маршруту. `$executionTime` — це час, необхідний для виконання маршруту (виклику контролера тощо).
+- **flight.view.rendered**: `function(string $template_file_path, float $executionTime)` Викликається після рендерингу подання. `$executionTime` — це час, необхідний для рендерингу шаблону. **Примітка: якщо ви переопределите метод `render`, вам потрібно буде повторно викликати цю подію.**
+- **flight.response.sent**: `function(Response $response, float $executionTime)` Викликається після відправлення відповіді клієнту. `$executionTime` — це час, необхідний для побудови відповіді.
\ No newline at end of file
diff --git a/content/v3/zh/awesome-plugins/apm.md b/content/v3/zh/awesome-plugins/apm.md
new file mode 100644
index 0000000..7e6be4c
--- /dev/null
+++ b/content/v3/zh/awesome-plugins/apm.md
@@ -0,0 +1,277 @@
+# FlightPHP APM 文档
+
+欢迎来到 FlightPHP APM——你应用的个人性能教练!本指南是你设置、使用和掌握应用性能监控(APM)与 FlightPHP 的路线图。无论你是在追踪慢请求,还是想要对延迟图表感到著迷,我们都能帮你搞定。让我们使你的应用更快,让用户更开心,让调试过程变得轻松!
+
+## 为什么 APM 重要
+
+想象一下:你的应用就像一家繁忙的餐厅。没有办法追踪订单需要多长时间或厨房的瓶颈在哪里,你就只能猜测客户为什么会不高兴地离开。APM 就是你的副厨师——它监控每一个步骤,从进入的请求到数据库查询,并标记任何让你放慢速度的东西。慢页面会失去用户(研究表明,如果网站加载超过 3 秒,53% 的用户会离开!),APM 帮助你在问题出现之前就发现这些问题。这是一种主动的安心——减少“为什么会出错?”的时刻,增加“看看这个多流畅!”的胜利。
+
+## 安装
+
+从 Composer 开始:
+
+```bash
+composer require flightphp/apm
+```
+
+你需要:
+- **PHP 7.4+**:保持与 LTS Linux 发行版的兼容,同时支持现代 PHP。
+- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**:我们正在提升的轻量级框架。
+
+## 开始使用
+
+这是你逐步达到 APM 极致的步骤:
+
+### 1. 注册 APM
+
+将以下代码放入 `index.php` 或 `services.php` 文件中开始追踪:
+
+```php
+use flight\apm\logger\LoggerFactory;
+use flight\Apm;
+
+$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
+$Apm = new Apm($ApmLogger);
+$Apm->bindEventsToFlightInstance($app);
+```
+
+**这里发生了什么?**
+- `LoggerFactory::create()` 获取你的配置(稍后会详细介绍),并设置一个记录器——默认是 SQLite。
+- `Apm` 是明星——它监听 Flight 的事件(请求、路由、错误等)并收集指标。
+- `bindEventsToFlightInstance($app)` 将所有内容绑定到你的 Flight 应用上。
+
+**专业提示:采样**
+如果你的应用很忙,记录 *每一个* 请求可能会过载。使用采样率(0.0 到 1.0):
+
+```php
+$Apm = new Apm($ApmLogger, 0.1); // 记录 10% 的请求
+```
+
+这保持性能灵活,同时仍然给你提供坚实的数据。
+
+### 2. 配置
+
+运行此命令生成你的 `.runway-config.json`:
+
+```bash
+php vendor/bin/runway apm:init
+```
+
+**这做了什么?**
+- 启动一个向导,询问原始指标来源(源)和处理后数据去向(目标)。
+- 默认是 SQLite——例如,`sqlite:/tmp/apm_metrics.sqlite` 作为源,另一个作为目标。
+- 你会得到如下配置:
+ ```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"
+ }
+ }
+ ```
+
+**为什么要两个位置?**
+原始指标堆积得很快(想想未过滤的日志)。工作进程将它们处理成一个结构化的目标,以便于仪表盘显示。保持整洁!
+
+### 3. 使用工作进程处理指标
+
+工作进程将原始指标转换为仪表盘准备的数据。运行一次:
+
+```bash
+php vendor/bin/runway apm:worker
+```
+
+**它在做什么?**
+- 从你的源读取(例如,`apm_metrics.sqlite`)。
+- 将多达 100 个指标(默认批量大小)处理到你的目标。
+- 完成时停止或如果没有剩余指标。
+
+**保持运行**
+对于实时应用,你会希望进行持续处理。这里是你的选择:
+
+- **守护进程模式**:
+ ```bash
+ php vendor/bin/runway apm:worker --daemon
+ ```
+ 永久运行,处理进来的指标。非常适合开发或小型设置。
+
+- **Cron 表**:
+ 将以下内容添加到你的 Cron 表(`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` 重新连接
+ ```
+ 即使你注销也能保持运行。
+
+- **自定义调整**:
+ ```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 分钟后退出。
+
+**为什么要费心?**
+没有工作进程,你的仪表盘将为空。它是原始日志和可操作洞察之间的桥梁。
+
+### 4. 启动仪表盘
+
+查看你应用的生命体征:
+
+```bash
+php vendor/bin/runway apm:dashboard
+```
+
+**这是什么?**
+- 在 `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`: 如果 PHP 不在你的 PATH 中,请指向 PHP。
+
+在浏览器中访问该 URL 并进行探索!
+
+#### 生产模式
+
+在生产环境中,你可能需要尝试一些技巧以使仪表盘正常运行,因为可能有防火墙和其他安全措施。以下是一些选项:
+
+- **使用反向代理**:设置 Nginx 或 Apache 将请求转发到仪表盘。
+- **SSH 隧道**:如果你可以 SSH 进入服务器,使用 `ssh -L 8080:localhost:8001 youruser@yourserver` 将仪表盘隧道到本地机器。
+- **VPN**:如果你的服务器在 VPN 后面,连接到 VPN 并直接访问仪表盘。
+- **配置防火墙**:为你的 IP 或服务器网络打开 8001 端口(或你设置的任意端口)。
+- **配置 Apache/Nginx**:如果你在应用程序前有 Web 服务器,可以将其配置到域名或子域。如果这样做,你需要将文档根设置为 `/path/to/your/project/vendor/flightphp/apm/dashboard`。
+
+#### 想要不同的仪表盘?
+
+如果你愿意,你可以构建自己的仪表盘!查看 `vendor/flightphp/apm/src/apm/presenter` 目录,获取关于如何呈现数据以供自己仪表盘的想法!
+
+## 仪表盘功能
+
+仪表盘是你的 APM HQ——这里是你将看到的内容:
+
+- **请求日志**:每个请求的时间戳、URL、响应代码和总时间。点击“详细信息”可查看中间件、查询和错误。
+- **最慢请求**:占用时间最多的前 5 个请求(例如,“/api/heavy”耗时 2.5 秒)。
+- **最慢路由**:按平均时间排序的前 5 个路由——非常适合发现模式。
+- **错误率**:失败请求的百分比(例如,2.3% 500s)。
+- **延迟百分位**:95%(p95)和99%(p99)响应时间——了解你的最坏情况。
+- **响应代码图表**:可视化一段时间内的 200s、404s、500s。
+- **长查询/中间件**:前 5 个慢数据库调用和中间件层。
+- **缓存命中/未命中**:你的缓存有多常发挥作用。
+
+**额外功能**:
+- 按“最后一小时”、“昨天”或“上周”进行过滤。
+- 切换深色模式以适应那些深夜的工作。
+
+**示例**:
+对 `/users` 的请求可能显示:
+- 总时间:150ms
+- 中间件: `AuthMiddleware->handle`(50ms)
+- 查询: `SELECT * FROM users`(80ms)
+- 缓存: 在 `user_list` 上命中(5ms)
+
+## 添加自定义事件
+
+追踪任何内容,例如 API 调用或支付过程:
+
+```php
+use flight\apm\CustomEvent;
+
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('api_call', [
+ 'endpoint' => 'https://api.example.com/users',
+ 'response_time' => 0.25,
+ 'status' => 200
+]));
+```
+
+**它显示在哪里?**
+在仪表盘的请求详细信息下方“自定义事件”中——可展开并以漂亮的 JSON 格式显示。
+
+**使用案例**:
+```php
+$start = microtime(true);
+$apiResponse = file_get_contents('https://api.example.com/data');
+$app->eventDispatcher()->emit('apm.custom', new CustomEvent('external_api', [
+ 'url' => 'https://api.example.com/data',
+ 'time' => microtime(true) - $start,
+ 'success' => $apiResponse !== false
+]));
+```
+现在你将看到该 API 是否拖慢了你的应用!
+
+## 数据库监控
+
+如下追踪 PDO 查询:
+
+```php
+use flight\database\PdoWrapper;
+
+$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite');
+$Apm->addPdoConnection($pdo);
+```
+
+**你得到了什么**:
+- 查询文本(例如,`SELECT * FROM users WHERE id = ?`)
+- 执行时间(例如,0.015s)
+- 行计数(例如,42)
+
+**注意**:
+- **可选**:如果你不需要数据库跟踪,可以跳过此步骤。
+- **仅限 PdoWrapper**:核心 PDO 尚未连接——敬请期待!
+- **性能警告**:在数据库负荷较重的网站上记录每个查询可能会导致减速。使用采样(`$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`: 持续运行——理想用于实时监控。
+
+**示例**:
+```bash
+php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
+```
+连续运行一个小时,每次处理 100 个指标。
+
+## 故障排除
+
+卡住了?试试这些方法:
+
+- **没有仪表盘数据?**
+ - 工作进程在运行吗?检查 `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 日志是否有堆栈跟踪。
+
+- **仪表盘无法启动?**
+ - 8001 端口已经在使用?使用 `--port 8080`。
+ - 找不到 PHP?使用 `--php-path /usr/bin/php`。
+ - 防火墙阻止?打开端口或使用 `--host localhost`。
+
+- **太慢了?**
+ - 降低采样率: `$Apm = new Apm($ApmLogger, 0.05)`(5%)。
+ - 减少批量大小: `--batch_size 20`。
\ 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 cb3dd7f..d534b7d 100644
--- a/content/v3/zh/awesome-plugins/awesome_plugins.md
+++ b/content/v3/zh/awesome-plugins/awesome_plugins.md
@@ -1,79 +1,84 @@
-# 精彩的插件
+# 超级插件
-Flight 拥有强大的扩展性。有许多插件可以用来为你的 Flight 应用程序添加功能。其中一些是 Flight 团队正式支持的,其他的是轻量级库,可以帮助你入门。
+Flight 非常可扩展。 有许多插件可以用于为您的 Flight 应用程序添加功能。 一些得到 Flight 团队的官方支持,而另一些则是微型/轻量库,以帮助您入门。
## API 文档
-API 文档对于任何 API 都至关重要。它帮助开发者理解如何与你的 API 交互以及期望返回什么。有几种工具可供你为你的 Flight 项目生成 API 文档。
+API 文档对任何 API 都至关重要。它帮助开发人员理解如何与您的 API 交互以及可以期待什么回报。 有一些工具可帮助您为您的 Flight 项目生成 API 文档。
-- [FlightPHP OpenAPI 生成器](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 生成器](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 一起使用。
+- beta[flightphp/apm](/awesome-plugins/apm) - Flight APM 是一个简单的 APM 库,可用于监控您的 Flight 应用程序。 它可以用于监控您的应用程序的性能并帮助您识别瓶颈。
## 身份验证/授权
-身份验证和授权对于任何需要控制访问的应用程序至关重要。
+身份验证和授权对任何需要控制谁可以访问什么的应用程序至关重要。
-- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight 权限库。这个库提供了一种简单的方式来为你的应用程序添加用户和应用级别的权限。
+- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight 权限库。 这个库是向您的应用程序添加用户和应用程序级权限的一种简单方式。
## 缓存
-缓存是加速你的应用程序的一个很好的方式。有许多缓存库可以与 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 应用程序。
## Cookies
-Cookies 是在客户端存储小数据块的很好方式。它们可以用来存储用户偏好、应用程序设置等。
+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 一起使用。它有许多面板可以帮助你调试应用程序。它也非常容易扩展,并添加自己的面板。
-- [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](/awesome-plugins/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](/awesome-plugins/pdo-wrapper) - 官方 Flight PDO 包装器,属于核心部分。这是一个简单的包装器,帮助简化编写查询和执行它们的过程。它不是 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) - 简单的工作队列是一个可以用于异步处理工作的库。它可以与 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 会话库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。
-- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、段、会话加密)。使用 PHP open_ssl 可选地加密/解密会话数据。
+- official [flightphp/session](/awesome-plugins/session) - 官方 Flight 会话库。这是一个简单的会话库,可以用于存储和检索会话数据。 它使用 PHP 内置的会话处理。
+- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 可选地对会话数据进行加密/解密。
## 模板
-模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可以与 Flight 一起使用。
+模板是任何具有用户界面的 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。 扩展和添加您自己的过滤器和函数也非常简单。
## 贡献
-有插件想要分享吗?提交一个拉取请求,将其添加到列表中!
\ No newline at end of file
+您是否有想要分享的插件? 提交拉取请求以将其添加到列表中!
\ No newline at end of file
diff --git a/content/v3/zh/awesome-plugins/tracy_extensions.md b/content/v3/zh/awesome-plugins/tracy_extensions.md
index c8d3cfa..6b87ad1 100644
--- a/content/v3/zh/awesome-plugins/tracy_extensions.md
+++ b/content/v3/zh/awesome-plugins/tracy_extensions.md
@@ -1,32 +1,32 @@
-## Tracy Flight Panel Extensions
+Tracy Flight 面板扩展
=====
-这是一组扩展,可以让与 Flight 的工作变得更加丰富。
+这是一个扩展集,使得与 Flight 的工作更加丰富。
- Flight - 分析所有 Flight 变量。
-- Database - 分析在页面上运行的所有查询(如果您正确初始化了数据库连接)
-- Request - 分析所有 `$_SERVER` 变量,并检查所有全局有效负载(`$_GET`,`$_POST`,`$_FILES`)
-- Session - 分析所有 `$_SESSION` 变量(如果会话处于活动状态)。
+- Database - 分析页面上运行的所有查询(如果您正确初始化了数据库连接)
+- Request - 分析所有 `$_SERVER` 变量并检查所有全局有效负载 (`$_GET`, `$_POST`, `$_FILES`)
+- Session - 如果会话处于活动状态,则分析所有 `$_SESSION` 变量。
这是面板

-每个面板都显示关于您的应用程序非常有帮助的信息!
+每个面板都显示关于您的应用程序的非常有用的信息!



-单击[这里](https://github.com/flightphp/tracy-extensions)查看代码。
+点击 [这里](https://github.com/flightphp/tracy-extensions) 查看代码。
安装
-------
-运行 `composer require flightphp/tracy-extensions --dev`,您就开始了!
+运行 `composer require flightphp/tracy-extensions --dev`,您就可以开始了!
配置
-------
-您需要做很少的配置才能启动此功能。在使用此功能之前,您需要初始化 Tracy 调试器[https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide):
+要使其启动,您需要进行的配置非常少。您需要在使用此 [https://tracy.nette.org/en/guide](https://tracy.nette.org/en/guide) 之前先启动 Tracy 调试器:
```php
register('session', Session::class);
if(Debugger::$showBar === true) {
- // 这需为false,否则 Tracy 无法实际渲染 :(
+ // 这需要为 false,否则 Tracy 不能实际渲染 :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
-// 路由和其他事物...
+// 路由和其他内容...
Flight::start();
```
### Latte
-如果您在项目中安装了 Latte,您可以使用 Latte 面板来分析您的模板。您可以将 Latte 实例传递给 `TracyExtensionLoader` 构造函数的第二个参数中的 `latte` 键。
+如果您的项目中安装了 Latte,您可以使用 Latte 面板来分析您的模板。您可以将 Latte 实例传递给 `TracyExtensionLoader` 构造函数,在第二个参数中使用 `latte` 键。
```php
@@ -100,12 +102,13 @@ $app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
- // 这是您向 Tracy 添加 Latte 面板的位置
+ // 这是您将 Latte 面板添加到 Tracy 的地方
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
- // 这需为false,否则 Tracy 无法实际渲染 :(
+ // 这需要为 false,否则 Tracy 不能实际渲染 :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
+```
\ No newline at end of file
diff --git a/content/v3/zh/learn/events.md b/content/v3/zh/learn/events.md
index 114ba12..9aa4b9f 100644
--- a/content/v3/zh/learn/events.md
+++ b/content/v3/zh/learn/events.md
@@ -1,82 +1,82 @@
# Flight PHP 中的事件系统 (v3.15.0+)
-Flight PHP 引入了一个轻量级且直观的事件系统,让你可以在应用中注册和触发自定义事件。通过添加 `Flight::onEvent()` 和 `Flight::triggerEvent()`,你可以在应用的生命周期的关键时刻挂钩,或定义自己的事件,以使代码更加模块化和可扩展。这些方法是 Flight 的**可映射方法**的一部分,意味着你可以重写它们的行为以满足你的需求。
+Flight PHP 引入了一个轻量且直观的事件系统,允许您在应用程序中注册和触发自定义事件。通过 `Flight::onEvent()` 和 `Flight::triggerEvent()` 的添加,您现在可以挂钩在应用程序生命周期的关键时刻,或定义自己的事件,以使您的代码更加模块化和可扩展。这些方法是 Flight 的 **可映射方法** 的一部分,意味着您可以覆盖它们的行为以满足您的需求。
-本指南涵盖了开始使用事件所需的所有知识,包括它们的价值、如何使用它们以及实际示例,帮助初学者理解它们的威力。
+本指南涵盖了您开始使用事件所需了解的一切,包括它们的重要性、如何使用它们,以及帮助初学者理解它们强大功能的实际示例。
## 为什么使用事件?
-事件允许你将应用的不同部分分开,以防彼此依赖过重。这种分离——通常称为**解耦**——使得你的代码更容易更新、扩展或调试。你可以将逻辑分割成更小的、独立的部分,以响应特定的操作(事件),而不是将所有内容写在一个大块中。
+事件允许您将应用程序的不同部分分开,以避免它们过于依赖彼此。这种分离——通常称为 **解耦**——使您的代码更易于更新、扩展或调试。您可以将逻辑拆分为更小的独立部分,以响应特定的操作(事件),而不是将所有内容写在一个大块中。
-想象一下你正在构建一个博客应用:
-- 当用户发布评论时,你可能想要:
- - 将评论保存到数据库中。
- - 向博客主发送电子邮件。
+想象一下您正在构建一个博客应用程序:
+- 当用户发布评论时,您可能想要:
+ - 将评论保存到数据库。
+ - 向博客所有者发送电子邮件。
- 记录该操作以确保安全。
-如果没有事件,你会将所有这一切塞进一个函数中。有了事件,你可以将其拆分:一部分保存评论,另一部分触发一个类似 `'comment.posted'` 的事件,独立的监听器处理电子邮件和日志记录。这保持了代码的整洁,并让你在不触及核心逻辑的情况下添加或移除特性(如通知)。
+没有事件,您会将所有这些内容塞进一个函数里。使用事件,您可以将其拆开:一部分保存评论,另一部分触发事件,例如 `'comment.posted'`,而独立的监听器处理电子邮件和日志记录。这保持了代码的整洁,并允许您在不触及核心逻辑的情况下添加或删除功能(例如通知)。
-### 常见用法
-- **日志记录**:记录登录或错误等操作,而不混乱主代码。
-- **通知**:当某些事情发生时发送电子邮件或警报。
-- **更新**:刷新缓存或通知其他系统有关更改。
+### 常见用途
+- **日志记录**:记录诸如登录或错误等操作,而不会使主代码变得复杂。
+- **通知**:当发生某些事情时,发送电子邮件或警报。
+- **更新**:刷新缓存或通知其他系统有关更改的信息。
## 注册事件监听器
-要监听一个事件,请使用 `Flight::onEvent()`。此方法允许你定义在事件发生时应该执行的操作。
+要监听事件,请使用 `Flight::onEvent()`。该方法让您定义当事件发生时应执行的操作。
### 语法
```php
Flight::onEvent(string $event, callable $callback): void
```
-- `$event`:事件的名称 (例如:`'user.login'`)。
+- `$event`:您的事件名称(例如,`'user.login'`)。
- `$callback`:当事件被触发时要运行的函数。
-### 工作原理
-你通过告诉 Flight 事件发生时该做什么来“订阅”一个事件。回调可以接受事件触发时传递的参数。
+### 它是如何工作的
+您通过告诉 Flight 在事件发生时要做什么来“订阅”事件。回调可以接受从事件触发器传递的参数。
-Flight 的事件系统是同步的,这意味着每个事件监听器按顺序执行,一个接一个。当你触发一个事件时,该事件所有注册的监听器将在代码继续之前运行完成。这一点很重要,因为与异步事件系统不同,异步事件系统的监听器可能会并行运行或在稍后的时间运行。
+Flight 的事件系统是同步的,这意味着每个事件监听器按顺序执行,一个接一个。当您触发事件时,所有为该事件注册的监听器将在您的代码继续之前完成运行。这一点很重要,因为它与异步事件系统不同,在异步事件系统中,监听器可能会并行运行或在稍后时间执行。
### 简单示例
```php
Flight::onEvent('user.login', function ($username) {
- echo "欢迎回来,$username!";
+ echo "欢迎回来,$username!";
});
```
-在这里,当触发 `'user.login'` 事件时,它会以用户的名字向其问候。
+在这里,当触发 `'user.login'` 事件时,它会通过名字向用户致意。
### 关键点
-- 你可以为同一事件添加多个监听器——它们将按照你注册的顺序运行。
-- 回调可以是一个函数、一个匿名函数,或者一个类的方法。
+- 您可以为同一事件添加多个监听器——它们将按您注册的顺序运行。
+- 回调可以是一个函数、一个匿名函数或一个类中的方法。
## 触发事件
-要使事件发生,请使用 `Flight::triggerEvent()`。这告诉 Flight 运行所有为该事件注册的监听器,并传递你提供的任何数据。
+要使事件发生,使用 `Flight::triggerEvent()`。这告诉 Flight 运行该事件所有已注册的监听器,并传递您提供的任何数据。
### 语法
```php
Flight::triggerEvent(string $event, ...$args): void
```
-- `$event`:你要触发的事件名称(必须与已注册的事件匹配)。
-- `...$args`:可选参数,以发送给监听器(可以是任何数量的参数)。
+- `$event`:您要触发的事件名称(必须与注册的事件匹配)。
+- `...$args`:要传递给监听器的可选参数(可以是任意数量的参数)。
### 简单示例
```php
$username = 'alice';
Flight::triggerEvent('user.login', $username);
```
-这触发了 `'user.login'` 事件,并将 `'alice'` 发送给我们之前定义的监听器,它将输出:`欢迎回来,alice!`。
+这触发了 `'user.login'` 事件,并将 `'alice'` 发送给我们之前定义的监听器,输出将是:`欢迎回来,alice!`。
### 关键点
-- 如果没有注册监听器,则什么也不会发生——你的应用不会崩溃。
+- 如果没有注册监听器,则什么都不会发生——您的应用不会崩溃。
- 使用扩展运算符 (`...`) 灵活地传递多个参数。
### 注册事件监听器
...
-**停止进一步监听器**:
-如果监听器返回 `false`,则该事件的后续监听器将不会执行。这允许你基于特定条件停止事件链。请记住,监听器的顺序很重要,因为第一个返回 `false` 的将阻止其余的运行。
+**停止进一步的监听器**:
+如果某个监听器返回 `false`,则不会执行该事件的其他监听器。这使您能够根据特定条件停止事件链。请记住,监听器的顺序很重要,因为第一个返回 `false` 的监听器将阻止其余的执行。
**示例**:
```php
@@ -87,36 +87,36 @@ Flight::onEvent('user.login', function ($username) {
}
});
Flight::onEvent('user.login', function ($username) {
- sendWelcomeEmail($username); // 这不会被发送
+ sendWelcomeEmail($username); // 这个永远不会被发送
});
```
## 重写事件方法
-`Flight::onEvent()` 和 `Flight::triggerEvent()` 可以被[扩展](/learn/extending),这意味着你可以重新定义它们的工作原理。这对于想要自定义事件系统的高级用户很有好处,例如添加日志记录或改变事件的分发方式。
+`Flight::onEvent()` 和 `Flight::triggerEvent()` 可以被 [扩展](/learn/extending),这意味着您可以重新定义它们的工作方式。这对于想要自定义事件系统的高级用户非常有用,比如添加日志记录或更改事件的分发方式。
### 示例:自定义 `onEvent`
```php
Flight::map('onEvent', function (string $event, callable $callback) {
- // 记录每个事件注册
- error_log("为新事件监听器添加:$event");
- // 调用默认行为(假设有一个内部事件系统)
+ // 记录每个事件的注册
+ error_log("新增事件监听器添加:$event");
+ // 调用默认行为(假设是一个内部事件系统)
Flight::_onEvent($event, $callback);
});
```
-现在,每次注册事件时,都会在继续之前进行日志记录。
+现在,每次您注册事件时,它都会在继续之前记录下来。
-### 为什么要重写?
+### 为什么重写?
- 添加调试或监控。
-- 在某些环境中限制事件(例如,在测试时禁用)。
-- 与其他事件库集成。
+- 在某些环境中限制事件(例如,在测试中禁用)。
+- 与不同的事件库集成。
## 将事件放在哪里
-作为初学者,你可能会想:*我应该在哪里注册应用中的所有这些事件?* Flight 的简洁性意味着没有严格的规则——你可以将它们放在任何适合你项目的地方。不过,保持它们的组织有助于你在应用增长时维护代码。以下是一些实用的选项和最佳实践,旨在符合 Flight 轻量级的特性:
+作为初学者,您可能会想:*我应该在应用程序中在哪里注册所有这些事件?* Flight 的简单性意味着没有严格的规则——您可以将它们放在适合您项目的任何地方。然而,保持事件的组织性有助于在应用程序增长时维护代码。以下是一些实用的选项和最佳实践,专门针对 Flight 的轻量特性:
-### 选项 1:在主 `index.php` 中
-对于小型应用或快速原型,你可以直接在 `index.php` 文件中注册事件,与路由共存。这使得一切保持在一个地方,对于优先考虑简洁性是可以的。
+### 选项 1:在您的主要 `index.php`
+对于小型应用或快速原型,您可以直接在 `index.php` 文件中注册事件,与路由放在一起。这将所有内容放在一个地方,当简便性是您的优先考虑时,这是可以的。
```php
require 'vendor/autoload.php';
@@ -130,16 +130,16 @@ Flight::onEvent('user.login', function ($username) {
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "登录成功!";
+ echo "已登录!";
});
Flight::start();
```
-- **优点**:简单,没有额外文件,适合小项目。
-- **缺点**:随着应用增加更多事件和路由,可能会变得杂乱。
+- **优点**:简单,没有额外文件,非常适合小项目。
+- **缺点**:随着应用程序使用更多事件和路由,将会变得混乱。
-### 选项 2:独立的 `events.php` 文件
-对于稍大的应用,可以考虑将事件注册移动到一个专用文件中,例如 `app/config/events.php`。在 `index.php` 中在路由之前包含此文件。这模仿了 Flight 项目中路由通常组织在 `app/config/routes.php` 的方式。
+### 选项 2:一个单独的 `events.php` 文件
+对于稍大的应用程序,考虑将事件注册移动到一个专用文件,如 `app/config/events.php`。在路由之前将此文件包含到您的 `index.php` 中。这与在 Flight 项目中的 `app/config/routes.php` 中组织路由的方式类似。
```php
// app/config/events.php
@@ -148,7 +148,7 @@ Flight::onEvent('user.login', function ($username) {
});
Flight::onEvent('user.registered', function ($email, $name) {
- echo "发送邮件给 $email: 欢迎,$name!";
+ echo "发送到 $email 的电子邮件:欢迎,$name!";
});
```
@@ -160,39 +160,39 @@ require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
- echo "登录成功!";
+ echo "已登录!";
});
Flight::start();
```
-- **优点**:保持 `index.php` 专注于路由,逻辑组织事件,便于查找和编辑。
-- **缺点**:增加了一点结构,可能对非常小的应用来说显得过于复杂。
+- **优点**:使 `index.php` 专注于路由,逻辑地组织事件,易于查找和编辑。
+- **缺点**:增加了一点结构,对于非常小的应用可能会觉得过于复杂。
-### 选项 3:靠近触发的位置
-另一种方法是在触发事件的地方注册事件,例如在控制器或路由定义内。如果事件特定于应用的某一部分,这种方法效果很好。
+### 选项 3:在触发它们的地方附近
+另一种方法是在触发事件的地方附近注册事件,例如在控制器或路由定义中。这对于特定于应用程序某一部分的事件效果很好。
```php
Flight::route('/signup', function () {
// 在这里注册事件
Flight::onEvent('user.registered', function ($email) {
- echo "欢迎邮件已发送给 $email!";
+ echo "欢迎邮件发送到 $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
- echo "注册成功!";
+ echo "已注册!";
});
```
-- **优点**:将相关代码保持在一起,适合孤立的特性。
-- **缺点**:事件注册分散,可能很难一目了然所有事件;如果不小心容易导致重复注册。
+- **优点**:将相关代码放在一起,适合独立特性。
+- **缺点**:事件注册分散,使得难以一次查看所有事件;如果不小心还可能有重复注册的风险。
### Flight 的最佳实践
-- **从简单开始**:对于小型应用,将事件放在 `index.php` 中。这样快捷且符合 Flight 的极简主义。
-- **聪明地扩展**:随着应用的扩大(例如,超过5-10个事件),使用 `app/config/events.php` 文件。这是自然的提升,就像组织路由一样,可以让你的代码整洁而不增加复杂的框架。
-- **避免过度设计**:除非你的应用规模很大,否则不要创建完整的“事件管理器”类或目录——Flight 追求简洁,保持轻量化。
+- **从简单开始**:对于小型应用,将事件放在 `index.php` 中。这快速且与 Flight 的简约性相符合。
+- **智能增长**:随着应用程序的扩展(例如,超过 5-10 个事件),使用 `app/config/events.php` 文件。这是一个自然的进步,类似于组织路由,同时保持代码整洁而不增加复杂的框架。
+- **避免过度工程**:除非您的应用程序变得庞大,否则不要创建一个完整的“事件管理器”类或目录——Flight 以简单著称,因此保持轻量。
-### 提示:按目的分组
-在 `events.php` 中,以注释分组相关事件(例如,把所有用户相关事件放在一起)以保持清晰度:
+### 小贴士:按目的分组
+在 `events.php` 中,将相关事件分组(例如,将所有与用户相关的事件放在一起),并添加注释以增加清晰度:
```php
// app/config/events.php
@@ -201,7 +201,7 @@ Flight::onEvent('user.login', function ($username) {
error_log("$username 登录");
});
Flight::onEvent('user.registered', function ($email) {
- echo "欢迎到 $email!";
+ echo "欢迎来到 $email!";
});
// 页面事件
@@ -210,80 +210,86 @@ Flight::onEvent('page.updated', function ($pageId) {
});
```
-这种结构可扩展且对初学者友好。
+这种结构扩展良好,并且对初学者友好。
## 初学者示例
-让我们通过一些真实场景来演示事件的工作原理以及为什么它们有用。
+让我们通过一些现实场景展示事件的工作原理以及它们的价值。
### 示例 1:记录用户登录
```php
-// 步骤 1:注册监听器
+// 第 1 步:注册监听器
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
error_log("$username 于 $time 登录");
});
-// 步骤 2:在应用中触发它
+// 第 2 步:在您的应用中触发它
Flight::route('/login', function () {
- $username = 'bob'; // 假设这是来自表单
+ $username = 'bob'; // 假装这是来自表单的
Flight::triggerEvent('user.login', $username);
- echo "嗨,$username!";
+ echo "嗨,$username!";
});
```
-**为什么这有用**:登录代码不需要知道日志记录的事情——它只是触发事件。你可以稍后添加更多监听器(例如,发送欢迎邮件),而无需更改路由。
+**这有何用处**:登录代码不需要知道日志记录——它只需触发事件。您可以稍后添加更多监听器(例如,发送欢迎邮件),而无需更改路由。
### 示例 2:通知新用户
```php
-// 注册新注册的监听器
+// 新注册的监听器
Flight::onEvent('user.registered', function ($email, $name) {
// 模拟发送电子邮件
- echo "发送邮件给 $email: 欢迎,$name!";
+ echo "发送邮件到 $email:欢迎,$name!";
});
-// 在有人注册时触发它
+// 当有人注册时触发
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
- echo "感谢注册!";
+ echo "感谢注册!";
});
```
-**为什么这有用**:注册逻辑专注于创建用户,而事件处理通知。你可以稍后添加更多监听器(例如,记录注册)而不需要更改逻辑。
+**这有何用处**:注册逻辑专注于创建用户,而事件处理通知。您可以稍后添加更多监听器(例如,记录注册)。
### 示例 3:清除缓存
```php
// 清除缓存的监听器
Flight::onEvent('page.updated', function ($pageId) {
unset($_SESSION['pages'][$pageId]); // 如果适用,清除会话缓存
- echo "已清除页面 $pageId 的缓存。";
+ echo "页面 $pageId 的缓存已清除。";
});
-// 当页面被编辑时触发
+// 当编辑页面时触发
Flight::route('/edit-page/(@id)', function ($pageId) {
// 假装我们更新了页面
Flight::triggerEvent('page.updated', $pageId);
echo "页面 $pageId 已更新。";
});
```
-**为什么这有用**:编辑代码不需要关心缓存的事情——它只是发出更新的信号。应用的其他部分可以根据需要做出反应。
+**这有何用处**:编辑代码不关心缓存——它只发出更新信号。应用程序的其他部分可以根据需要作出反应。
## 最佳实践
-- **清晰命名事件**:使用特定名称,如 `'user.login'` 或 `'page.updated'`,这样显而易见它们的作用。
-- **保持监听器简单**:不要在监听器中放入缓慢或复杂的任务——保持应用的快速。
-- **测试你的事件**:手动触发事件以确保监听器按预期工作。
-- **明智使用事件**:它们非常适合解耦,但过多可能使代码难以跟随——在合适的时候使用它们。
+- **清晰命名事件**:使用具体的名称,如 `'user.login'` 或 `'page.updated'`,这样一目了然它们的作用。
+- **保持监听器简单**:不要在监听器中放置缓慢或复杂的任务——保持应用程序快速。
+- **测试事件**:手动触发它们,以确保监听器按预期工作。
+- **明智地使用事件**:它们很适合解耦,但过多可能使代码难以理解——当合适时使用它们。
-Flight PHP 中的事件系统以及 `Flight::onEvent()` 和 `Flight::triggerEvent()` 为你提供了一种简单而强大的方式来构建灵活的应用。通过让应用的不同部分通过事件进行通信,你可以保持代码组织良好、可重用且易于扩展。无论是记录操作、发送通知还是管理更新,事件都能帮助你做到这一点,而不让你的逻辑纠缠在一起。而且,能够重写这些方法使你有自由度来根据需要调整系统。从单个事件开始,看看它如何改变你应用的结构!
+Flight PHP 的事件系统,结合 `Flight::onEvent()` 和 `Flight::triggerEvent()`,为您提供了一种构建灵活应用程序的简单而强大的方式。通过允许应用程序的不同部分通过事件进行通信,您可以保持代码的组织性、可重用性,并易于扩展。无论您是在记录操作、发送通知还是管理更新,事件有助于您在不纠缠逻辑的情况下实现这些功能。此外,通过能够重写这些方法,您有自由度根据需要定制系统。从一个简单的事件开始,看看它如何改变您应用的结构!
## 内置事件
-Flight PHP 还附带了一些内置事件,你可以利用这些事件来挂钩到框架的生命周期。这些事件在请求/响应周期的特定时点触发,允许你在某些操作发生时执行自定义逻辑。
+Flight PHP 附带了一些内置事件,您可以使用这些事件来挂接到框架的生命周期。这些事件在请求/响应周期的特定点被触发,允许您在发生某些操作时执行自定义逻辑。
### 内置事件列表
-- `flight.request.received`:当请求被接收、解析和处理时触发。
-- `flight.route.middleware.before`:在执行前中间件后触发。
-- `flight.route.middleware.after`:在执行后中间件后触发。
-- `flight.route.executed`:在路由被执行和处理后触发。
-- `flight.response.sent`:在响应被发送到客户端后触发。
\ No newline at end of file
+- **flight.request.received**:`function(Request $request)` 当请求被接收、解析和处理时触发。
+- **flight.error**:`function(Throwable $exception)` 在请求生命周期中发生错误时触发。
+- **flight.redirect**:`function(string $url, int $status_code)` 当发起重定向时触发。
+- **flight.cache.checked**:`function(string $cache_key, bool $hit, float $executionTime)` 调用时触发,检查特定键的缓存,及缓存是命中还是未命中。
+- **flight.middleware.before**:`function(Route $route)` 在执行前中间件之后触发。
+- **flight.middleware.after**:`function(Route $route)` 在执行后中间件之后触发。
+- **flight.middleware.executed**:`function(Route $route, $middleware, string $method, float $executionTime)` 在执行任何中间件之后触发
+- **flight.route.matched**:`function(Route $route)` 当路由匹配时触发,但尚未运行。
+- **flight.route.executed**:`function(Route $route, float $executionTime)` 在路由执行和处理后触发。`$executionTime` 是执行路由(调用控制器等)所花费的时间。
+- **flight.view.rendered**:`function(string $template_file_path, float $executionTime)` 在视图渲染之后触发。`$executionTime` 是渲染模板所需的时间。**注意:如果您重写了 `render` 方法,则需要重新触发此事件。**
+- **flight.response.sent**:`function(Response $response, float $executionTime)` 在响应发送给客户端后触发。`$executionTime` 是构建响应所需的时间。
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..f7d8bc8
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,28 @@
+{
+ "name": "flight-docs",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "husky": "^9.1.7"
+ }
+ },
+ "node_modules/husky": {
+ "version": "9.1.7",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
+ "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "husky": "bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6b87ff3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,8 @@
+{
+ "devDependencies": {
+ "husky": "^9.1.7"
+ },
+ "scripts": {
+ "prepare": "husky"
+ }
+}
diff --git a/phpstan.neon b/phpstan.neon
index d7f8d45..228f205 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -5,4 +5,8 @@ parameters:
level: 0
paths:
- app
- - public
+ - public/index.php
+ excludePaths:
+ - app/cache/*
+ - app/views
+ - app/config/config.php
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..590132c
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ tests/Unit
+
+
+ tests/Feature
+
+
+
+
+ app
+
+
+
+
+
+
+
+
diff --git a/public/index.php b/public/index.php
index ada9b35..b4c9320 100644
--- a/public/index.php
+++ b/public/index.php
@@ -24,5 +24,4 @@
Cessna 402 (Wings)
by Dick Williams, rjw1@tyrell.net
*/
-$ds = DIRECTORY_SEPARATOR;
-require_once __DIR__ . $ds . '..' . $ds . 'app' . $ds . 'config' . $ds . 'bootstrap.php';
+require_once __DIR__ . '/../app/config/bootstrap.php';
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..5e4ff3e
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
\ No newline at end of file
diff --git a/rector.php b/rector.php
index 1315462..667586e 100644
--- a/rector.php
+++ b/rector.php
@@ -7,6 +7,14 @@
return RectorConfig::configure()
->withPaths([
__DIR__ . '/app',
- __DIR__ . '/public',
+ __DIR__ . '/public/index.php',
])
- ->withPhpSets(php82: true);
+ ->withSkipPath(__DIR__ . '/vendor')
+ ->withSkipPath(__DIR__ . '/app/cache')
+ ->withSkipPath(__DIR__ . '/app/config/config.php')
+ ->withSkipPath(__DIR__ . '/app/views')
+ ->withPhpSets(php82: true)
+ ->withDeadCodeLevel(0)
+ ->withCodeQualityLevel(0)
+ ->withCodingStyleLevel(0)
+ ->withTypeCoverageLevel(0);
diff --git a/tests/Feature/AboutTest.php b/tests/Feature/AboutTest.php
new file mode 100644
index 0000000..9c47d37
--- /dev/null
+++ b/tests/Feature/AboutTest.php
@@ -0,0 +1,35 @@
+get(str_replace('//', '/', "./es/v3/$uri"));
+ $html = new DOMDocument;
+ @$html->loadHTML($response->getBody()->getContents());
+ $title = $html->getElementsByTagName('title')->item(0);
+
+ self::assertSame(200, $response->getStatusCode());
+ self::assertStringContainsString('Acerca de', $title->textContent);
+
+ self::assertStringContainsString(
+ 'Flight PHP Framework',
+ $title->textContent
+ );
+ }
+
+ static function aboutPageUrisDataProvider(): array {
+ return [
+ ['/'],
+ ['/about'],
+ ];
+ }
+}
diff --git a/tests/Feature/BootstrapTest.php b/tests/Feature/BootstrapTest.php
new file mode 100644
index 0000000..0d13de5
--- /dev/null
+++ b/tests/Feature/BootstrapTest.php
@@ -0,0 +1,35 @@
+get('./');
+ } catch (GuzzleException $exception) {
+ $message = $exception->getMessage();
+
+ self::assertStringContainsString('500', $message);
+
+ self::assertStringContainsString(
+ 'Config file not found. Please create a config.php file in the app/config directory to get started.',
+ $message
+ );
+ }
+
+ rename($backupConfigFilePath, $configFilePath);
+ }
+}
diff --git a/tests/Feature/FeatureTestCase.php b/tests/Feature/FeatureTestCase.php
new file mode 100644
index 0000000..b913ea5
--- /dev/null
+++ b/tests/Feature/FeatureTestCase.php
@@ -0,0 +1,27 @@
+ $_ENV['APP_URL']
+ ]);
+ }
+}
diff --git a/tests/Feature/InstallTest.php b/tests/Feature/InstallTest.php
new file mode 100644
index 0000000..b3ed86a
--- /dev/null
+++ b/tests/Feature/InstallTest.php
@@ -0,0 +1,23 @@
+get('./es/v3/install');
+ $html = new DOMDocument;
+ @$html->loadHTML($response->getBody()->getContents());
+ $title = $html->getElementsByTagName('title')->item(0);
+ $jumbotron = $html->getElementsByTagName('h1')->item(0);
+
+ self::assertSame(200, $response->getStatusCode());
+ self::assertStringContainsString('Instalación', $title->textContent);
+ self::assertSame('Instalación', $jumbotron->textContent);
+ }
+}
diff --git a/tests/Feature/RedirectionsTest.php b/tests/Feature/RedirectionsTest.php
new file mode 100644
index 0000000..14f44aa
--- /dev/null
+++ b/tests/Feature/RedirectionsTest.php
@@ -0,0 +1,51 @@
+get('./', [
+ 'allow_redirects' => false
+ ]);
+
+ self::assertSame(303, $response->getStatusCode());
+
+ self::assertStringContainsString(
+ '/en/v3/',
+ $response->getHeaderLine('location')
+ );
+ }
+
+ #[Test]
+ function it_redirects_to_version_when_only_language_is_specified(): void {
+ $response = self::$client->get('/en', [
+ 'allow_redirects' => false
+ ]);
+
+ self::assertSame(303, $response->getStatusCode());
+
+ self::assertStringContainsString(
+ '/en/v3/',
+ $response->getHeaderLine('location')
+ );
+ }
+
+ #[Test]
+ function it_redirects_to_default_language_and_version_when_only_section_and_subsection_is_specified(): void {
+ $response = self::$client->get('/section/subsection', [
+ 'allow_redirects' => false
+ ]);
+
+ self::assertSame(303, $response->getStatusCode());
+
+ self::assertStringContainsString(
+ '/en/v3/section/subsection/',
+ $response->getHeaderLine('location')
+ );
+ }
+}
diff --git a/tests/Feature/StatusCheckTest.php b/tests/Feature/StatusCheckTest.php
new file mode 100644
index 0000000..8bfbb4b
--- /dev/null
+++ b/tests/Feature/StatusCheckTest.php
@@ -0,0 +1,23 @@
+get('./api/status');
+
+ self::assertSame(200, $response->getStatusCode());
+
+ self::assertSame(
+ 'application/json',
+ mb_strtolower($response->getHeaderLine('content-type'))
+ );
+
+ self::assertSame('{"status":"ok"}', $response->getBody()->getContents());
+ }
+}
diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php
new file mode 100644
index 0000000..5e950bd
--- /dev/null
+++ b/tests/Unit/ConfigTest.php
@@ -0,0 +1,23 @@
+ $dsn
+ ]);
+
+ self::assertSame($dsn, $config['PDO_DSN']);
+ }
+}
diff --git a/tests/Unit/DocsLogicTest.php b/tests/Unit/DocsLogicTest.php
new file mode 100644
index 0000000..2651ac1
--- /dev/null
+++ b/tests/Unit/DocsLogicTest.php
@@ -0,0 +1,99 @@
+container = new Container;
+
+ $this->container->set(
+ Engine::class,
+ function (): Engine {
+ $this->engine = new Engine;
+ $this->engine->register('translator', CustomTranslator::class);
+
+ $this->engine->register(
+ 'cache',
+ Cache::class,
+ [__DIR__ . '/../cache/']
+ );
+
+ $this->engine->register('parsedown', Parsedown::class);
+
+ $this->engine->register(
+ 'latte',
+ LatteEngine::class,
+ [],
+ function (LatteEngine $latte): void {
+ $latte->setTempDirectory(__DIR__ . '/../cache/');
+ $latte->setLoader(new FileLoader(__DIR__ . '/../views/'));
+
+ $latte->addExtension(new TranslatorExtension(
+ $this
+ ->container
+ ->get(CustomTranslator::class)
+ ->translate(...),
+ ));
+ }
+ );
+
+ return $this->engine;
+ }
+ );
+
+ $this->docsLogic = $this->container->get(DocsLogic::class);
+ $_SERVER['HTTP_HOST'] = 'localhost';
+ }
+
+ #[Test]
+ function it_renders_a_page(): void {
+ $this->engine->request()->url = '/test?var=value';
+
+ self::expectOutputString(<<<'html'
+
+
diff --git a/tests/views/test.latte b/tests/views/test.latte
new file mode 100644
index 0000000..f2b5bb8
--- /dev/null
+++ b/tests/views/test.latte
@@ -0,0 +1,2 @@
+
+
{$variable}
diff --git a/translate_content.php b/translate_content.php
index d1e7903..3a82ace 100644
--- a/translate_content.php
+++ b/translate_content.php
@@ -63,7 +63,7 @@
$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 like 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. Please don't translate any URLs or you will break my app and I will lose my job if this is not done correctly!"
+ "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",