قم بإنشاء حزمة لـ Symfony 4 خطوة بخطوة

قبل نحو عام ، اتجهت شركتنا إلى فصل المونوليث الضخم في 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 { /** * {@inheritdoc} */ 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 { /** @var HealthInterface[] */ private $healthServices = []; public function addHealthService(HealthInterface $healthService) { $this->healthServices[] = $healthService; } /** * @Route("/health") * @return JsonResponse */ 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 { /** * @param HealthDataInterface[] $data */ 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; /** @var HealthInterface[] */ private $healthServices; /** @var SymfonyStyle */ 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 { /** * {@inheritdoc} */ 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'); //    $commandDefinition = new Definition(SendDataCommand::class); //        foreach ($config['senders'] as $serviceId) { $commandDefinition->addArgument(new Reference($serviceId)); } //       $commandDefinition->addTag('console.command', ['command' => SendDataCommand::COMMAND_NAME]); //     $container->setDefinition(SendDataCommand::class, $commandDefinition); } } 

هذا كل شيء ، فريقنا مصمم. الآن ، بعد إضافة الحزمة إلى المشروع ، عند الاستدعاء
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 --dev server 

الحزمة متصلة ، ويقوم 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; } } 

  • src/Service/Sender.php

وهنا يكون الأمر أسهل


 <?php namespace App\Service; use niklesh\HealthCheckBundle\Entity\HealthDataInterface; use niklesh\HealthCheckBundle\Service\HealthSenderInterface; class Sender implements HealthSenderInterface { /** * @param HealthDataInterface[] $data */ 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 متاح هنا .

Source: https://habr.com/ru/post/ar419451/


All Articles