قبل نحو عام ، اتجهت شركتنا إلى فصل المونوليث الضخم في Magento 1 إلى خدمات صغيرة. كأساس ، اختاروا فقط Symfony 4 ، الذي تم إصداره في الإصدار. خلال هذا الوقت قمت بتطوير العديد من المشاريع في هذا الإطار ، لكنني وجدت بشكل خاص أنه من المثير للاهتمام تطوير الحزم ، المكونات المعاد استخدامها لـ Symfony. تحت القطة ، دليل خطوة بخطوة حول تطوير حزمة HealthCheck للحصول على حالة / صحة الخدمة الصغيرة تحت Syfmony 4.1 ، والتي حاولت فيها أن أتطرق إلى اللحظات الأكثر إثارة للاهتمام وتعقيدًا (بالنسبة لي مرة واحدة).
في شركتنا ، يتم استخدام هذه الحزمة ، على سبيل المثال ، للحصول على حالة إعادة فهرسة المنتج في ElasticSearch - عدد المنتجات المضمنة في مطاط مع البيانات الحالية ، وعدد المنتجات التي تتطلب الفهرسة.
إنشاء هيكل عظمي للحزمة
في Symfony 3 ، كانت هناك حزمة مناسبة لإنشاء هياكل عظمية للحزمة ، ولكن في Symfony 4 لم تعد مدعومة ، وبالتالي عليك إنشاء الهيكل العظمي بنفسك. أبدأ في تطوير كل مشروع جديد من خلال إطلاق فريق
composer create-project symfony/skeleton health-check
يرجى ملاحظة أن Symfony 4 يدعم PHP 7.1+ ، لذلك إذا قمت بتشغيل هذا الأمر على الإصدار أدناه ، فستحصل على الهيكل العظمي لمشروع Symfony 3.
يقوم هذا الأمر بإنشاء مشروع Symfony 4.1 جديد بالبنية التالية:

من حيث المبدأ ، هذا ليس ضروريًا ، نظرًا لأن الملفات التي تم إنشاؤها لا نحتاج إليها كثيرًا في النهاية ، ولكن من الأنسب بالنسبة لي أن أنظف كل ما هو غير ضروري من إنشاء ما هو ضروري بيدي.
الملحن
الخطوة التالية هي تحرير composer.json
وفقًا لاحتياجاتنا. بادئ ذي بدء ، تحتاج إلى تغيير نوع نوع المشروع إلى symfony-bundle
سيساعد هذا Symfony Flex على تحديد عند إضافة حزمة إلى المشروع أنها حزمة Symfony حقًا ، وتوصيلها تلقائيًا وتثبيت الوصفة (ولكن المزيد عن ذلك لاحقًا). بعد ذلك ، تأكد من إضافة حقلي name
description
. يعتبر name
مهمًا أيضًا لأنه يحدد المجلد الذي سيتم وضع الحزمة فيه داخل vendor
.
"name": "niklesh/health-check", "description": "Health check bundle",
الخطوة المهمة التالية هي تعديل قسم التحميل autoload
، المسؤول عن تحميل فئات الحزمة. autoload
لبيئة العمل ، autoload-dev
لبيئة العمل.
"autoload": { "psr-4": { "niklesh\\HealthCheckBundle\\": "src" } }, "autoload-dev": { "psr-4": { "niklesh\\HealthCheckBundle\\Tests\\": "tests" } },
يمكن حذف قسم scripts
. يحتوي على نصوص برمجية لتجميع الأصول ومسح ذاكرة التخزين المؤقت بعد تنفيذ أوامر composer install
composer update
، ومع ذلك ، لا تحتوي الحزمة الخاصة بنا على أي أصول أو ذاكرة تخزين مؤقت ، وبالتالي فإن هذه الأوامر غير مجدية.
الخطوة الأخيرة هي تعديل الأقسام require-dev
المطلوب. ونتيجة لذلك نحصل على ما يلي:
"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" }
ألاحظ أنه سيتم تثبيت التبعيات من عند عندما تكون الحزمة متصلة بمسودة العمل.
نبدأ composer update
- يتم تثبيت التبعيات.
تنظيف غير ضروري
لذلك ، من الملفات المستلمة ، يمكنك حذف المجلدات التالية بأمان:
- bin - يحتوي على ملف
console
المطلوب لتشغيل أوامر Symfony - التكوين - يحتوي على ملفات التكوين للتوجيه ، والحزم المتصلة ،
الخدمات ، إلخ. - عام - يحتوي على
index.php
- نقطة دخول للتطبيق - يتم تخزين var - logs and
cache
هنا
نحذف أيضًا ملفات src/Kernel.php
و. .env
و. .env.dist
لا نحتاج إلى كل هذا لأننا نطور حزمة ، وليس تطبيقًا.
إنشاء هيكل حزمة
لذلك ، أضفنا التبعيات اللازمة وقمنا بتنظيف كل شيء لم يكن مطلوبًا من الحزمة الخاصة بنا. حان الوقت لإنشاء الملفات والمجلدات اللازمة لربط الحزمة بنجاح بالمشروع.
بادئ ذي بدء ، في المجلد src
، قم بإنشاء الملف HealthCheckBundle.php
بالمحتويات التالية:
<?php namespace niklesh\HealthCheckBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class HealthCheckBundle extends Bundle { }
يجب أن تكون هذه الفئة في كل حزمة تقوم بإنشائها. سيتم config/bundles.php
في config/bundles.php
للمشروع الرئيسي. بالإضافة إلى ذلك ، يمكنه التأثير على "بناء" الحزمة.
مكون الحزمة التالي المطلوب هو قسم DependencyInjection
. قم بإنشاء المجلد الذي يحمل نفس الاسم بملفين:
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; } }
هذا الملف مسؤول عن تحليل والتحقق من صحة تكوين الحزمة من ملفات Yaml أو xml. سنقوم بتعديله في وقت لاحق.
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'); } }
هذا الملف مسؤول عن تحميل ملفات تكوين الحزمة وإنشاء خدمات "التعريف" وتسجيلها وتحميل المعلمات في حاوية وما إلى ذلك.
والخطوة الأخيرة في هذه المرحلة هي إضافة ملف src/Resources/services.yaml
، والذي سيحتوي على وصف لخدمات الحزمة الخاصة بنا. اتركه فارغًا الآن.
HealthInterface
ستكون المهمة الرئيسية لحزمتنا هي إرجاع البيانات حول المشروع الذي يتم استخدامه فيه. لكن جمع المعلومات هو عمل الخدمة نفسها ، يمكن لحزمتنا أن تشير فقط إلى تنسيق المعلومات التي يجب أن ترسلها الخدمة إليها ، والطريقة التي ستتلقى هذه المعلومات. في تنفيذي ، يجب على جميع الخدمات (وقد يكون هناك العديد) التي تجمع المعلومات تنفيذ واجهة HealthInterface
مع طريقتين: getName
و getHealthInfo
. يجب أن يقوم الأخير بإرجاع كائن يقوم بتنفيذ واجهة HealthDataInterface
.
أولاً ، أنشئ واجهة بيانات 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; }
يجب أن تحتوي البيانات على حالة عدد صحيح ومعلومات إضافية (والتي ، بالمناسبة ، قد تكون فارغة).
نظرًا لأن تنفيذ هذه الواجهة على الأرجح سيكون نموذجيًا لمعظم الأحفاد ، فقد قررت إضافته إلى 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; } }
أخيرًا ، أضف الواجهة الخاصة بخدمات جمع البيانات src/Service/HealthInterface.php
:
<?php namespace niklesh\HealthCheckBundle\Service; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; interface HealthInterface { public function getName(): string; public function getHealthInfo(): HealthDataInterface; }
تحكم
سيقدم المتحكم بيانات عن المشروع في مسار واحد فقط. ولكن هذا المسار سيكون هو نفسه لجميع المشاريع التي تستخدم هذه الحزمة: /health
ومع ذلك ، فإن مهمة وحدة التحكم لدينا ليست فقط لإعطاء البيانات ، ولكن أيضًا HealthInterface
من الخدمات التي تنفذ HealthInterface
؛ وبناءً على ذلك ، يجب على وحدة التحكم تخزين الروابط لكل من هذه الخدمات. addHealthService
طريقة addHealthService
مسؤولة عن إضافة الخدمات إلى وحدة التحكم
أضف وحدة تحكم 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)); } }
تجميع
يمكن لـ Symfony تنفيذ إجراءات معينة مع الخدمات التي تطبق واجهة معينة. يمكنك استدعاء طريقة معينة ، وإضافة علامة ، ولكن لا يمكنك أخذ جميع هذه الخدمات وإدخالها في خدمة أخرى (وهي وحدة التحكم). يتم حل هذه المشكلة في 4 مراحل:
نضيف إلى كل من خدماتنا HealthInterface
تنفذ علامة HealthInterface
.
أضف ثابت TAG
إلى الواجهة:
interface HealthInterface { public const TAG = 'health.service'; }
بعد ذلك ، تحتاج إلى إضافة هذه العلامة إلى كل خدمة. في حالة تكوين المشروع ، يمكن أن يكون هذا
التنفيذ في ملف config/services.yaml
في قسم _instanceof
. في حالتنا ، هذا
سيبدو الإدخال كما يلي:
serivces: _instanceof: niklesh\HealthCheckBundle\Service\HealthInterface: tags: - !php/const niklesh\HealthCheckBundle\Service\HealthInterface::TAG
ومن حيث المبدأ ، إذا قمت بتعيين تهيئة الحزمة للمستخدم ، فإنها ستعمل ، ولكن في رأيي هذا ليس النهج الصحيح ، يجب توصيل الحزمة نفسها بشكل صحيح وتكوينها مع الحد الأدنى من تدخل المستخدم عند إضافتها إلى المشروع. قد يتذكر شخص ما أن لدينا خدماتنا الخاصة. services.yaml
داخل الحزمة ، ولكن لا ، لن يساعدنا. يعمل هذا الإعداد فقط إذا كان في ملف المشروع ، وليس في الحزمة.
لا أعرف ما إذا كان هذا خطأ أم ميزة ، ولكن الآن لدينا ما لدينا. لذلك ، سيتعين علينا التسلل إلى عملية تجميع الحزم.
انتقل إلى src/HealthCheckBundle.php
وأعد تعريف طريقة build
:
<?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); } }
الآن سيتم وضع علامة على كل فئة تطبق HealthInterface
.
تسجيل وحدة التحكم كخدمة
في الخطوة التالية ، سنحتاج إلى الاتصال بوحدة التحكم كخدمة ، في مرحلة تجميع الحزمة. في حالة العمل مع المشروع ، يتم تسجيل جميع الفئات كخدمات بشكل افتراضي ، ولكن في حالة العمل مع الحزمة ، يجب علينا تحديد الفئات التي ستكون خدمات بشكل صريح ، ووضع حجج لها ، والإشارة إلى ما إذا كانت ستكون عامة.
افتح ملف src/Resources/config/services.yaml
وأضف المحتويات التالية
services: niklesh\HealthCheckBundle\Controller\HealthController: autoconfigure: true
قمنا بتسجيل وحدة التحكم بشكل صريح كخدمة ، والآن يمكن الوصول إليها في مرحلة التجميع.
إضافة خدمات لوحدة التحكم.
في مرحلة تجميع الحاوية والحزم ، لا يمكننا العمل إلا مع تعريفات الخدمة. في هذه المرحلة ، نحتاج إلى أخذ تعريف HealthController
إلى أنه بعد إنشائه ، من الضروري أن نضيف إليه جميع الخدمات المميزة HealthController
. بالنسبة لمثل هذه العمليات في الحزم ، تكون الفئات التي تنفذ الواجهة مسؤولة
Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface
قم 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)]); } } }
كما ترى ، نستخدم أولاً طريقة findDefinition
لأخذ وحدة التحكم ، ثم - جميع الخدمات عن طريق العلامة ، ثم في حلقة ، أضف مكالمة إلى طريقة addHealthService
لكل خدمة تم العثور عليها ، حيث نقوم بتمرير الرابط إلى هذه الخدمة.
باستخدام CompilerPath
الخطوة الأخيرة هي إضافة HealthServicePath
إلى عملية تجميع الحزم. دعنا نعود إلى فئة HealthCheckBundle
طريقة build
أكثر قليلاً. نتيجة لذلك ، نحصل على:
<?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); } }
بشكل أساسي ، في هذه المرحلة ، الحزمة الخاصة بنا جاهزة للاستخدام. يمكنه العثور على خدمات جمع المعلومات والعمل معها وإعطاء إجابة عند الوصول /health
(تحتاج فقط إلى إضافة إعدادات التوجيه عند الاتصال) ، لكنني قررت أن أضع فيها القدرة على إرسال المعلومات عند الطلب فقط ، ولكن أيضًا توفير القدرة على إرسال هذه المعلومات إلى أو ، على سبيل المثال ، استخدام طلب POST أو من خلال مدير قائمة الانتظار.
HealthSenderInterface
الغرض من هذه الواجهة هو وصف الفئات المسؤولة عن إرسال البيانات في مكان ما. قم src/Service/HealthSenderInterface
في 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; }
كما ترى ، ستقوم طريقة send
بطريقة ما بمعالجة مصفوفة البيانات المستلمة من جميع الفئات التي تطبق HealthInterface
ثم ترسلها إلى المكان الذي تحتاج إليه.
هناك حاجة إلى getName
و getName
ببساطة لعرض المعلومات عند تشغيل أمر وحدة التحكم.
Senddatacommand
بدء إرسال البيانات إلى موارد الجهات الخارجية سيكون أمر وحدة التحكم SendDataCommand
. وتتمثل مهمتها في جمع البيانات للتوزيع ، ثم استدعاء طريقة send
على كل من خدمات التوزيع. من الواضح أن هذا الأمر سيكرر جزئياً منطق وحدة التحكم ، ولكن ليس في كل شيء.
<?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
، HealthServicesPath
إضافة خدمات جمع البيانات إلى الفريق.
<?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)]); } } }
كما ترى ، يأخذ الأمر في المُنشئ مجموعة من المرسلين. في هذه الحالة ، لن تتمكن من استخدام ميزة الربط التلقائي للاعتماد ؛ فنحن بحاجة إلى إنشاء وتسجيل فريق بأنفسنا. السؤال الوحيد هو أي خدمات المرسل لإضافتها إلى هذا الأمر. سنشير إلى معرفهم في تكوين الحزمة مثل هذا:
health_check: senders: - '@sender.service1' - '@sender.service2'
لا تزال مجموعتنا لا تعرف كيفية التعامل مع مثل هذه التكوينات ، وسوف نعلمها. انتقل إلى 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(); $rootNode = $treeBuilder->root('health_check'); $rootNode ->children() ->arrayNode('senders') ->scalarPrototype()->end() ->end() ->end() ; return $treeBuilder; } }
يحدد هذا الرمز أن العقدة الجذرية ستكون العقدة health_check
، والتي ستحتوي على senders
صفيف senders
، والتي بدورها ستحتوي على عدد معين من الأسطر. هذا كل شيء ، الآن تعرف حزمتنا كيفية التعامل مع التكوين ، الذي أوضحناه أعلاه. حان الوقت لتسجيل الفريق. للقيام بذلك ، انتقل إلى HealthCheckExtension
وقم بإضافة التعليمات البرمجية التالية:
<?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');
هذا كل شيء ، فريقنا مصمم. الآن ، بعد إضافة الحزمة إلى المشروع ، عند الاستدعاء
bin/console
سنرى قائمة بالأوامر ، بما في ذلك أوامرنا: health:send-info
، يمكنك تسميتها بنفس الطريقة: bin/console health:send-info
الحزمة الخاصة بنا جاهزة. حان الوقت لاختباره على المشروع. إنشاء مشروع فارغ:
composer create-project symfony/skeleton health-test-project
أضف حزمة المخبوزات الطازجة إليها ، لذلك نضيف قسم repositories
في composer.json
:
"repositories": [ { "type": "vcs", "url": "https://github.com/HEKET313/health-check" } ]
وتنفيذ الأمر:
composer require niklesh/health-check
وللبداية الأسرع ، أضف خادم سيمفونية إلى مشروعنا:
composer req
الحزمة متصلة ، ويقوم Symfony Flex تلقائيًا config/bundles.php
بـ config/bundles.php
، ولكن لإنشاء ملفات التكوين تلقائيًا ، تحتاج إلى إنشاء وصفة. حول الوصفات مطلية بشكل جميل في مقال آخر هنا: https://habr.com/post/345382/ - لذا ارسم كيفية إنشاء الوصفات ، إلخ. لن أكون هنا ، ولا توجد وصفة لهذه الحزمة حتى الآن.
ومع ذلك ، هناك حاجة إلى ملفات التكوين ، لذلك قم بإنشائها باستخدام مقابض:
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'
تحتاج الآن إلى تنفيذ فئات إرسال المعلومات للفريق وفئة جمع المعلومات
src/Service/DataCollector.php
كل شيء بسيط للغاية هنا.
<?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; } }
وهنا يكون الأمر أسهل
<?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'; } }
انتهى! امسح ذاكرة التخزين المؤقت وابدأ تشغيل الخادم
bin/console cache:clear bin/console server:start
يمكنك الآن تجربة فريقنا:
bin/console health:send-info
نحصل على مثل هذا الاستنتاج الجميل:

أخيرًا ، نحن نطرق طريقنا http://127.0.0.1:8000/health
ونحصل على نتيجة أقل جمالا ، ولكن أيضا الاستنتاج:
[{"name":"Data collector","info":{"status":1,"additional_info":{"some_data":"some_value"}}}]
هذا كل شيء! آمل أن يساعد هذا البرنامج التعليمي البسيط شخصًا ما على فهم أساسيات كتابة حزم Symfony 4.
كود مصدر PS متاح هنا .