Vor etwa einem Jahr war unser Unternehmen auf dem Weg zur Trennung des riesigen Monolithen auf Magento 1 in Microservices. Als Basis wählten sie nur Symfony 4, das in der Version veröffentlicht wurde. Während dieser Zeit entwickelte ich mehrere Projekte auf diesem Framework, aber ich fand es besonders interessant, Bundles zu entwickeln und Komponenten für Symfony wiederzuverwenden. Unter der Katze eine Schritt-für-Schritt-Anleitung zur Entwicklung des HealthCheck-Bundles zur Ermittlung des Status / der Gesundheit eines Microservices unter Syfmony 4.1, in der ich versuchte, die interessantesten und komplexesten (für mich einmal) Momente zu berühren.
In unserem Unternehmen wird dieses Bundle beispielsweise verwendet, um den Status eines Produkt-Neuindex in ElasticSearch abzurufen - wie viele Produkte sind in Elastic mit aktuellen Daten enthalten und wie viele müssen indiziert werden.
Erstellen Sie ein Bündelskelett
In Symfony 3 gab es ein praktisches Bundle zum Generieren von Bundle-Skeletten, in Symfony 4 wird es jedoch nicht mehr unterstützt und daher müssen Sie das Skelett selbst erstellen. Ich beginne die Entwicklung jedes neuen Projekts mit der Gründung eines Teams
composer create-project symfony/skeleton health-check
Bitte beachten Sie, dass Symfony 4 PHP 7.1+ unterstützt. Wenn Sie diesen Befehl in der folgenden Version ausführen, erhalten Sie das Projektskelett für Symfony 3.
Dieser Befehl erstellt ein neues Symfony 4.1-Projekt mit der folgenden Struktur:

Im Prinzip ist dies nicht erforderlich, da wir am Ende nicht so viel Dateien erstellen, aber es ist für mich bequemer, alles zu reinigen, was nicht benötigt wird, als das Notwendige mit meinen Händen zu erstellen.
composer.json
Der nächste Schritt besteht darin, composer.json
an unsere Bedürfnisse anzupassen. Zunächst müssen Sie den Typ des Projekttyps in symfony-bundle
diese Weise kann Symfony Flex beim Hinzufügen eines Bundles zum Projekt feststellen, dass es sich tatsächlich um ein Symfony-Bundle handelt, es automatisch verbinden und das Rezept installieren (dazu später mehr). Stellen Sie als Nächstes sicher, dass Sie die Felder name
und description
hinzufügen. name
ist auch wichtig, da er bestimmt, in welchem Ordner innerhalb des vendor
Bundle abgelegt wird.
"name": "niklesh/health-check", "description": "Health check bundle",
Der nächste wichtige Schritt ist das Bearbeiten des autoload
Abschnitts, der für das Laden der Bundle-Klassen verantwortlich ist. autoload
für die Arbeitsumgebung, autoload-dev
für die Arbeitsumgebung.
"autoload": { "psr-4": { "niklesh\\HealthCheckBundle\\": "src" } }, "autoload-dev": { "psr-4": { "niklesh\\HealthCheckBundle\\Tests\\": "tests" } },
Der scripts
kann gelöscht werden. Es enthält Skripte zum Zusammenstellen von Assets und zum Löschen des Caches nach Ausführung der composer install
und composer update
Befehle. Unser Bundle enthält jedoch keine Assets oder Caches. Daher sind diese Befehle unbrauchbar.
Der letzte Schritt besteht darin, die Abschnitte require
und require-dev
zu bearbeiten. Als Ergebnis erhalten wir Folgendes:
"require": { "php": "^7.1.3", "ext-ctype": "*", "ext-iconv": "*", "symfony/flex": "^1.0", "symfony/framework-bundle": "^4.1", "sensio/framework-extra-bundle": "^5.2", "symfony/lts": "^4@dev", "symfony/yaml": "^4.1" }
Ich stelle fest, dass die Abhängigkeiten von require
installiert werden, wenn das Bundle mit dem Arbeitsentwurf verbunden ist.
Wir starten das composer update
- Abhängigkeiten sind installiert.
Unnötige Reinigung
Aus den empfangenen Dateien können Sie also die folgenden Ordner sicher löschen:
- bin - enthält die
console
, die zum Ausführen von Symfony-Befehlen erforderlich ist - config - enthält Konfigurationsdateien für das Routing, verbundene Bundles,
Dienstleistungen usw. - public - enthält
index.php
- Einstiegspunkt in die Anwendung - Hier werden Var - Logs und
cache
gespeichert
Wir löschen auch die .env.dist
src/Kernel.php
, .env
, .env.dist
Wir brauchen das alles nicht, weil wir ein Bundle entwickeln, keine Anwendung.
Bündelstruktur erstellen
Also haben wir die notwendigen Abhängigkeiten hinzugefügt und alles, was nicht benötigt wurde, aus unserem Bundle entfernt. Es ist Zeit, die erforderlichen Dateien und Ordner zu erstellen, um das Bundle erfolgreich mit dem Projekt zu verbinden.
Erstellen Sie zunächst im Ordner src
die Datei HealthCheckBundle.php
mit folgendem Inhalt:
<?php namespace niklesh\HealthCheckBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class HealthCheckBundle extends Bundle { }
Eine solche Klasse sollte in jedem von Ihnen erstellten Bundle enthalten sein. Er wird in die config/bundles.php
Hauptprojekts aufgenommen. Außerdem kann er den "Build" des Bundles beeinflussen.
Die nächste benötigte Bundle-Komponente ist der Abschnitt DependencyInjection
. Erstellen Sie den gleichnamigen Ordner mit 2 Dateien:
src/DependencyInjection/Configuration.php
<?php namespace niklesh\HealthCheckBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $treeBuilder->root('health_check'); return $treeBuilder; } }
Diese Datei ist für das Parsen und Überprüfen der Bundle-Konfiguration aus Yaml- oder XML-Dateien verantwortlich. Wir werden es später ändern.
src/DependencyInjection/HealthCheckExtension.php
<?php namespace niklesh\HealthCheckBundle\DependencyInjection; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; class HealthCheckExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $this->processConfiguration($configuration, $configs); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.yaml'); } }
Diese Datei ist für das Laden von Bundle-Konfigurationsdateien, das Erstellen und Registrieren von "Definitions" -Diensten, das Laden von Parametern in einen Container usw. verantwortlich.
Der letzte Schritt in dieser Phase ist das Hinzufügen der Datei src/Resources/services.yaml
, die eine Beschreibung der Dienste unseres Bundles enthält. Lass es jetzt leer.
HealthInterface
Die Hauptaufgabe unseres Bundles besteht darin, Daten über das Projekt zurückzugeben, in dem es verwendet wird. Das Sammeln von Informationen ist jedoch die Arbeit des Dienstes selbst. Unser Paket kann nur das Format der Informationen angeben, die der Dienst an ihn senden soll, und die Methode, mit der diese Informationen empfangen werden. In meiner Implementierung sollten alle Dienste (und möglicherweise mehrere), die Informationen sammeln, die HealthInterface
Schnittstelle mit zwei Methoden getName
: getName
und getHealthInfo
. Letzteres sollte ein Objekt zurückgeben, das die HealthDataInterface
Schnittstelle implementiert.
Erstellen Sie zunächst die Datenschnittstelle src/Entity/HealthDataInterface.php
:
<?php namespace niklesh\HealthCheckBundle\Entity; interface HealthDataInterface { public const STATUS_OK = 1; public const STATUS_WARNING = 2; public const STATUS_DANGER = 3; public const STATUS_CRITICAL = 4; public function getStatus(): int; public function getAdditionalInfo(): array; }
Die Daten müssen einen ganzzahligen Status und zusätzliche Informationen enthalten (die übrigens leer sein können).
Da die Implementierung dieser Schnittstelle höchstwahrscheinlich für die meisten Nachkommen typisch ist, habe ich beschlossen, sie dem src/Entity/CommonHealthData.php
:
<?php namespace niklesh\HealthCheckBundle\Entity; class CommonHealthData implements HealthDataInterface { private $status; private $additionalInfo = []; public function __construct(int $status) { $this->status = $status; } public function setStatus(int $status) { $this->status = $status; } public function setAdditionalInfo(array $additionalInfo) { $this->additionalInfo = $additionalInfo; } public function getStatus(): int { return $this->status; } public function getAdditionalInfo(): array { return $this->additionalInfo; } }
Fügen Sie abschließend die Schnittstelle für die Datenerfassungsdienste src/Service/HealthInterface.php
:
<?php namespace niklesh\HealthCheckBundle\Service; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; interface HealthInterface { public function getName(): string; public function getHealthInfo(): HealthDataInterface; }
Controller
Der Controller gibt Daten über das Projekt auf nur einer Route weiter. Diese Route ist jedoch für alle Projekte, die dieses Bundle verwenden, gleich: /health
Die Aufgabe unseres Controllers besteht jedoch nicht nur darin, Daten HealthInterface
, sondern sie auch aus den Diensten herauszuholen, die HealthInterface
implementieren. HealthInterface
muss der Controller Links zu jedem dieser Dienste speichern. Die addHealthService
Methode ist für das Hinzufügen von Diensten zum Controller verantwortlich
Fügen Sie den Controller src/Controller/HealthController.php
:
<?php namespace niklesh\HealthCheckBundle\Controller; use niklesh\HealthCheckBundle\Service\HealthInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; class HealthController extends AbstractController { private $healthServices = []; public function addHealthService(HealthInterface $healthService) { $this->healthServices[] = $healthService; } public function getHealth(): JsonResponse { return $this->json(array_map(function (HealthInterface $healthService) { $info = $healthService->getHealthInfo(); return [ 'name' => $healthService->getName(), 'info' => [ 'status' => $info->getStatus(), 'additional_info' => $info->getAdditionalInfo() ] ]; }, $this->healthServices)); } }
Zusammenstellung
Symfony kann bestimmte Aktionen mit Diensten ausführen, die eine bestimmte Schnittstelle implementieren. Sie können eine bestimmte Methode aufrufen, ein Tag hinzufügen, aber nicht alle diese Dienste in einen anderen Dienst (den Controller) übernehmen und einfügen. Dieses Problem wird in 4 Schritten gelöst:
Wir fügen jedem unserer HealthInterface
das HealthInterface
Tag hinzu.
Fügen Sie der Schnittstelle die TAG
Konstante hinzu:
interface HealthInterface { public const TAG = 'health.service'; }
Als Nächstes müssen Sie dieses Tag jedem Dienst hinzufügen. Bei der Projektkonfiguration kann dies sein
Implementieren Sie in der Datei config/services.yaml
im Abschnitt _instanceof
. In unserem Fall dies
Der Eintrag würde folgendermaßen aussehen:
serivces: _instanceof: niklesh\HealthCheckBundle\Service\HealthInterface: tags: - !php/const niklesh\HealthCheckBundle\Service\HealthInterface::TAG
Wenn Sie dem Benutzer die Konfiguration des Bundles zuweisen, funktioniert dies im Prinzip. Meiner Meinung nach ist dies jedoch nicht der richtige Ansatz. Das Bundle selbst muss beim Hinzufügen zum Projekt korrekt verbunden und mit minimalem Benutzereingriff konfiguriert werden. Jemand könnte sich daran erinnern, dass wir unsere eigenen services.yaml
im Bundle haben, aber nein, es wird uns nicht helfen. Diese Einstellung funktioniert nur, wenn sie sich in der Projektdatei befindet, nicht im Bundle.
Ich weiß nicht, ob dies ein Fehler oder eine Funktion ist, aber jetzt haben wir das, was wir haben. Daher müssen wir den Bundle-Kompilierungsprozess infiltrieren.
src/HealthCheckBundle.php
und definieren Sie die build
neu:
<?php namespace niklesh\HealthCheckBundle; use niklesh\HealthCheckBundle\Service\HealthInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; class HealthCheckBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->registerForAutoconfiguration(HealthInterface::class)->addTag(HealthInterface::TAG); } }
Jetzt wird jede Klasse, die HealthInterface
implementiert, mit Tags versehen.
Registrieren des Controllers als Dienst
Im nächsten Schritt müssen wir den Controller als Service kontaktieren, während wir das Bundle kompilieren. Bei der Arbeit mit dem Projekt werden dort standardmäßig alle Klassen als Dienste registriert. Bei der Arbeit mit dem Bundle müssen wir jedoch explizit festlegen, welche Klassen Dienste sein sollen, Argumente für sie angeben und angeben, ob sie öffentlich sein werden.
Öffnen Sie die Datei src/Resources/config/services.yaml
und fügen Sie den folgenden Inhalt hinzu
services: niklesh\HealthCheckBundle\Controller\HealthController: autoconfigure: true
Wir haben den Controller explizit als Service registriert, jetzt kann in der Kompilierungsphase darauf zugegriffen werden.
Hinzufügen von Diensten zum Controller.
In der Phase der Kompilierung des Containers und der Bundles können wir nur mit Service-Definitionen arbeiten. In diesem Stadium müssen wir die Definition des HealthController
und angeben, dass nach seiner Erstellung alle mit unserem Tag gekennzeichneten Dienste hinzugefügt werden müssen. Für solche Operationen in Bundles sind Klassen verantwortlich, die die Schnittstelle implementieren
Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface
Erstellen Sie die folgende src/DependencyInjection/Compiler/HealthServicePath.php
:
<?php namespace niklesh\HealthCheckBundle\DependencyInjection\Compiler; use niklesh\HealthCheckBundle\Controller\HealthController; use niklesh\HealthCheckBundle\Service\HealthInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; class HealthServicesPath implements CompilerPassInterface { public function process(ContainerBuilder $container) { if (!$container->has(HealthController::class)) { return; } $controller = $container->findDefinition(HealthController::class); foreach (array_keys($container->findTaggedServiceIds(HealthInterface::TAG)) as $serviceId) { $controller->addMethodCall('addHealthService', [new Reference($serviceId)]); } } }
Wie Sie sehen können, verwenden wir zuerst die findDefinition
Methode findDefinition
um den Controller findDefinition
übernehmen, dann - alle Dienste nach Tag und fügen dann in einer Schleife jedem gefundenen Dienst einen Aufruf der addHealthService
Methode hinzu, wobei wir den Link zu diesem Dienst übergeben.
CompilerPath
Der letzte Schritt besteht darin, unseren HealthServicePath
zum Bundle-Kompilierungsprozess hinzuzufügen. HealthCheckBundle
wir zur HealthCheckBundle
Klasse zurück und ändern die build
etwas weiter. Als Ergebnis erhalten wir:
<?php namespace niklesh\HealthCheckBundle; use niklesh\HealthCheckBundle\DependencyInjection\Compiler\HealthServicesPath; use niklesh\HealthCheckBundle\Service\HealthInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; class HealthCheckBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new HealthServicesPath()); $container->registerForAutoconfiguration(HealthInterface::class)->addTag(HealthInterface::TAG); } }
Grundsätzlich ist unser Bundle zu diesem Zeitpunkt einsatzbereit. Es kann Informationssammlungsdienste finden, mit ihnen arbeiten und bei Kontaktaufnahme /health
eine Antwort geben (Sie müssen nur Routing-Einstellungen hinzufügen, wenn Sie eine Verbindung herstellen), aber ich habe beschlossen, die Möglichkeit einzubauen, Informationen nicht nur auf Anfrage zu senden, sondern auch diese Informationen an zu senden oder beispielsweise mithilfe einer POST-Anforderung oder über einen Warteschlangenmanager.
HealthSenderInterface
Diese Schnittstelle soll die Klassen beschreiben, die für das Senden von Daten an einen Ort verantwortlich sind. Erstellen Sie es in src/Service/HealthSenderInterface
<?php namespace niklesh\HealthCheckBundle\Service; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; interface HealthSenderInterface { public function send(array $data): void; public function getDescription(): string; public function getName(): string; }
Wie Sie sehen können, verarbeitet die send
Methode das empfangene Datenarray von allen Klassen, die HealthInterface
implementieren, und sendet es dann an den gewünschten Ort.
Die getName
getDescription
und getName
werden lediglich benötigt, um Informationen anzuzeigen, wenn ein Konsolenbefehl ausgeführt wird.
Senddatacommand
Starten Sie das Senden von Daten an Ressourcen von Drittanbietern mit dem Konsolenbefehl SendDataCommand
. Seine Aufgabe besteht darin, Daten für die Verteilung zu sammeln und dann die send
für jeden der Verteilungsdienste aufzurufen. Offensichtlich wiederholt dieser Befehl teilweise die Logik der Steuerung, aber nicht in allem.
<?php namespace niklesh\HealthCheckBundle\Command; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; use niklesh\HealthCheckBundle\Service\HealthInterface; use niklesh\HealthCheckBundle\Service\HealthSenderInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Throwable; class SendDataCommand extends Command { public const COMMAND_NAME = 'health:send-info'; private $senders; private $healthServices; private $io; public function __construct(HealthSenderInterface... $senders) { parent::__construct(self::COMMAND_NAME); $this->senders = $senders; } public function addHealthService(HealthInterface $healthService) { $this->healthServices[] = $healthService; } protected function configure() { parent::configure(); $this->setDescription('Send health data by senders'); } protected function initialize(InputInterface $input, OutputInterface $output) { parent::initialize($input, $output); $this->io = new SymfonyStyle($input, $output); } protected function execute(InputInterface $input, OutputInterface $output) { $this->io->title('Sending health info'); try { $data = array_map(function (HealthInterface $service): HealthDataInterface { return $service->getHealthInfo(); }, $this->healthServices); foreach ($this->senders as $sender) { $this->outputInfo($sender); $sender->send($data); } $this->io->success('Data is sent by all senders'); } catch (Throwable $exception) { $this->io->error('Exception occurred: ' . $exception->getMessage()); $this->io->text($exception->getTraceAsString()); } } private function outputInfo(HealthSenderInterface $sender) { if ($name = $sender->getName()) { $this->io->writeln($name); } if ($description = $sender->getDescription()) { $this->io->writeln($description); } } }
HealthServicesPath
und schreiben dem Team zusätzliche Datenerfassungsdienste.
<?php namespace niklesh\HealthCheckBundle\DependencyInjection\Compiler; use niklesh\HealthCheckBundle\Command\SendDataCommand; use niklesh\HealthCheckBundle\Controller\HealthController; use niklesh\HealthCheckBundle\Service\HealthInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; class HealthServicesPath implements CompilerPassInterface { public function process(ContainerBuilder $container) { if (!$container->has(HealthController::class)) { return; } $controller = $container->findDefinition(HealthController::class); $commandDefinition = $container->findDefinition(SendDataCommand::class); foreach (array_keys($container->findTaggedServiceIds(HealthInterface::TAG)) as $serviceId) { $controller->addMethodCall('addHealthService', [new Reference($serviceId)]); $commandDefinition->addMethodCall('addHealthService', [new Reference($serviceId)]); } } }
Wie Sie sehen können, akzeptiert der Befehl im Konstruktor ein Array von Absendern. In diesem Fall können Sie die Funktion zur automatischen Bindung von Abhängigkeiten nicht verwenden. Wir müssen selbst ein Team erstellen und registrieren. Die Frage ist nur, welche Absenderdienste diesem Befehl hinzugefügt werden sollen. Wir werden ihre ID in der Bundle-Konfiguration wie folgt angeben:
health_check: senders: - '@sender.service1' - '@sender.service2'
Unser Bundle weiß immer noch nicht, wie man mit solchen Konfigurationen umgeht, wir werden es lehren. Gehen Sie zu Configuration.php
und fügen Sie den Konfigurationsbaum hinzu:
<?php namespace niklesh\HealthCheckBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('health_check'); $rootNode ->children() ->arrayNode('senders') ->scalarPrototype()->end() ->end() ->end() ; return $treeBuilder; } }
Dieser Code bestimmt, dass der health_check
der health_check
Knoten ist, der den senders
Array- senders
, der wiederum eine bestimmte Anzahl von Zeilen enthält. Das war's, jetzt weiß unser Bundle, wie man mit der oben beschriebenen Konfiguration umgeht. Es ist Zeit, das Team zu registrieren. Gehen Sie dazu zu HealthCheckExtension
und fügen Sie den folgenden Code hinzu:
<?php namespace niklesh\HealthCheckBundle\DependencyInjection; use niklesh\HealthCheckBundle\Command\SendDataCommand; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\Reference; class HealthCheckExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.yaml');
Das war's, unser Team ist entschlossen. Jetzt nach dem Hinzufügen des Bundles zum Projekt, wenn aufgerufen
bin/console
Wir sehen eine Liste von Befehlen, einschließlich unserer: health:send-info
, Sie können es genauso nennen: bin/console health:send-info
Unser Bundle ist fertig. Es ist Zeit, es am Projekt zu testen. Erstellen Sie ein leeres Projekt:
composer create-project symfony/skeleton health-test-project
Fügen Sie unser frisch gebackenes Bundle hinzu. Dazu fügen wir den Abschnitt repositories
in composer.json
:
"repositories": [ { "type": "vcs", "url": "https://github.com/HEKET313/health-check" } ]
Und führen Sie den Befehl aus:
composer require niklesh/health-check
Fügen Sie unserem Projekt für den schnellsten Start einen Symphony-Server hinzu:
composer req
Das Bundle ist verbunden, Symfony Flex verbindet es automatisch mit config/bundles.php
jedoch automatisch Konfigurationsdateien zu erstellen, müssen Sie ein Rezept erstellen. Über Rezepte wird in einem anderen Artikel hier wunderschön gemalt: https://habr.com/post/345382/ - also malen Sie, wie man Rezepte usw. erstellt. Ich werde nicht hier sein und es gibt noch kein Rezept für dieses Bundle.
Trotzdem werden Konfigurationsdateien benötigt, also erstellen Sie sie mit Handles:
config/routes/niklesh_health.yaml
health_check: resource: "@HealthCheckBundle/Controller/HealthController.php" prefix: / type: annotation
config/packages/hiklesh_health.yaml
health_check: senders: - 'App\Service\Sender'
Jetzt müssen Sie die Informationssendeklassen für das Team und die Informationssammelklasse implementieren
src/Service/DataCollector.php
Hier ist alles sehr einfach.
<?php namespace App\Service; use niklesh\HealthCheckBundle\Entity\CommonHealthData; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; use niklesh\HealthCheckBundle\Service\HealthInterface; class DataCollector implements HealthInterface { public function getName(): string { return 'Data collector'; } public function getHealthInfo(): HealthDataInterface { $data = new CommonHealthData(HealthDataInterface::STATUS_OK); $data->setAdditionalInfo(['some_data' => 'some_value']); return $data; } }
Und hier ist es noch einfacher
<?php namespace App\Service; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; use niklesh\HealthCheckBundle\Service\HealthSenderInterface; class Sender implements HealthSenderInterface { public function send(array $data): void { print "Data sent\n"; } public function getDescription(): string { return 'Sender description'; } public function getName(): string { return 'Sender name'; } }
Fertig! Leeren Sie den Cache und starten Sie den Server
bin/console cache:clear bin/console server:start
Jetzt können Sie unser Team ausprobieren:
bin/console health:send-info
Wir bekommen so ein schönes Fazit:

Schließlich klopfen wir auf unserer Route http://127.0.0.1:8000/health
und bekommen eine weniger schöne, aber auch Schlussfolgerung:
[{"name":"Data collector","info":{"status":1,"additional_info":{"some_data":"some_value"}}}]
Das ist alles! Ich hoffe, dieses einfache Tutorial hilft jemandem, die Grundlagen des Schreibens von Bundles für Symfony 4 zu verstehen.
PS- Quellcode finden Sie hier .