كيفية إعادة استخدام الكود مع حزم symfony 5؟ الجزء 4. ملحق حزمة المضيف

لنتحدث عن كيفية إيقاف النسخ واللصق بين المشاريع ونقل الشفرة إلى حزمة مكون إضافي symfony 5. يمكن إعادة استخدامها. ستؤدي سلسلة من المقالات التي تلخص تجربتي مع الحزم عمليًا إلى إنشاء الحد الأدنى من الحزم وإعادة صياغة التطبيق التجريبي إلى الاختبارات ودورة إصدار الحزمة.


عند تصميم حزمة ، تحتاج إلى التفكير في ما يجب أن يكون مغلفًا بداخلها ، وما الذي يجب أن يكون متاحًا للمستخدم. هل يجب أن تحتوي الحزمة على وظائف ثابتة أم يجب أن تكون مرنة وتسمح لنفسها بالتوسع؟ إذا كانت المرونة مطلوبة ، فأنت بحاجة إلى توفير بعض نقاط التكامل لتوسيع الحزمة ، واجهتها.


دعونا نحاول تقديم مثل هذه النقاط في تطبيقنا التجريبي. في هذه المقالة:


  • ربط المنطق المخصص بحزمة
  • وضع العلامات
  • تمرير مترجم
  • خدمات التكوين التلقائي

محتوى المسلسل

إذا لم تكمل البرنامج التعليمي باستمرار ، فقم بتنزيل التطبيق من المستودع وانتقل إلى فرع التكامل 3 .


تعليمات تثبيت وبدء المشروع في ملف README.md.
ستجد النسخة النهائية من التعليمات البرمجية لهذه المقالة في فرع 4-تمديد .


مهمة


يحتوي التقويم على وظيفة تصدير الأحداث إلى GoogleCalendar أو iCalendar.
مهمتنا هي جعل حزمتنا أكثر مرونة وإضافة القدرة لمستخدمي الحزمة لتوسيعها بتنسيقات التصدير الخاصة بهم في تطبيقاتهم.


على سبيل المثال ، أضف التصدير إلى ملف JSON. هيا بنا نبدأ.



كيف يتم تنظيم تصدير الأحداث؟


لفهم كيفية إضافة تنسيق جديد ، دعنا نرى كيف يعمل EventExporter .


يتم تنفيذ منطق التصدير في المكون EventExporterالموجود في services/EventExporter. لقد قمنا بنقلها بالفعل إلى الحزمة وقمنا بتصحيح أسماء مساحة الاسم. ملفات المكونات الرئيسية هي:


  • ExporterInterface محاكاة تنسيق تصدير الحدث و
  • ExporterManager,

ExporterInterface.


— , ( Google Calendar), ( iCalendar). inline. EventController::export(), .


,


  • inline

2 AbtractInlineExporter AbstractFileExporter. ( ), , (ExportedFile).


2 — GoogleCalendarExporter ICalendarExporter.


, inline , , .



- JSON-.


:


git checkout 4-extend -- src/Service/EventExporter/JsonExporter.php

src/Service/EventExporter/JsonExporter.php:


<?php
declare(strict_types=1);

namespace App\Service\EventExporter;

use bravik\CalendarBundle\Entity\Event;
use bravik\CalendarBundle\Service\EventExporter\AbstractFileExporter;
use bravik\CalendarBundle\Service\EventExporter\ExportedFile;

/**
 * Generates a JSON file
 */
class JsonExporter extends AbstractFileExporter
{
    private const DATE_FORMAT = 'Y-m-d H:i:s';

    public function getName(): string
    {
        return ' JSON';
    }

    public function getType(): string
    {
        return 'json-file';
    }

    public function export(Event $event): ExportedFile
    {
        $data = [
            'id'            => $event->getId(),
            'title'         => $event->getTitle(),
            'description'   => $event->getDescription(),
            'venueName'     => $event->getVenueName(),
            'venueAddress'  => $event->getVenueAddress(),
            'startsAt'      => $event->getStartsAt()->format(self::DATE_FORMAT),
            'endsAt'        => $event->getEndsAt() ? $event->getEndsAt()->format(self::DATE_FORMAT) : null,
        ];

        return new ExportedFile('event.json', 'application/json', json_encode($data));
    }
}

?


DI- config/services.yaml . ExporterManager .


Symfony - . , , ExporterManager services.yaml . :


bravik\CalendarBundle\Service\EventExporter\ExporterManager:
    arguments:
        $exporters:
            - '@bravik\CalendarBundle\Service\EventExporter\Exporters\GoogleCalendarExporter'
            - '@bravik\CalendarBundle\Service\EventExporter\Exporters\ICalendarExporter'
            - 'App\Service\EventExporter\Exporters\JsonExporter'

: , , , .


, - , , ExporterManager - ? .


, . .

ExporterManager.


, , ExporterManager::registerExporter(). . , - registerExporter. DI-.



Symfony . — , DI- - . , ExporterManager.


JsonExporter services.yaml -:


App\Service\EventExporter\JsonExporter:
    tags: ['bravik.calendar.exporter']

services.yaml :


bravik\CalendarBundle\Service\EventExporter\Exporters\GoogleCalendarExporter:
    tags: ['bravik.calendar.exporter']
bravik\CalendarBundle\Service\EventExporter\Exporters\ICalendarExporter:
    tags: ['bravik.calendar.exporter']

, , , vendor.package.name.



Symfony 3.4 .


bravik.calendar.exporter ExporterManager. services.yaml:


bravik\CalendarBundle\Service\EventExporter\ExporterManager:
    arguments:
        $exporters: !tagged bravik.calendar.exporter

!tagged <tag-name> iterable , . typehint ExporterManager:


    public function __construct(iterable $exporters) {
    //...
    }

, .


, « » « JSON», JSON-.


( - , 4-extend .)


!tagged <tag-name>, , — , . .


Compiler Pass


services.yaml DI- . . Symfony , , PHP-. Symfony .

Compiler Pass. Symfony Compiler Pass.


, , ExporterManager.


bundles/CalendarBundle/src/DependencyInjection/Compiler/ExporterRegistrationPass.php, CompilerPassInterface:


namespace bravik\CalendarBundle\DependencyInjection\Compiler;

use bravik\CalendarBundle\Service\EventExporter\ExporterManager;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ExporterRegistrationPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->has(ExporterManager::class)) {
            return;
        }

        $exporterManagerDefinition = $container->findDefinition(ExporterManager::class);

        $taggedServices = $container->findTaggedServiceIds('bravik.calendar.exporter');

        $exporterReferences = [];
        foreach ($taggedServices as $id => $tags) {
            $exporterReferences[] = new Reference($id);
        }

        $exporterManagerDefinition->setArguments(['$exporters' => $exporterReferences]);
    }
}

Compiler Pass src/CalendarBundle. Bundle Bundle::build() :


    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new ExporterRegistrationPass());
    }

, pass , die("pass") process . pass — .


?


ExporterManager , DI-.
ExporterManager :


$exporterManagerDefinition = $container->findDefinition(ExporterManager::class);

Definition?


, - (Definition).


DI- , , «». Definition «»: , .

, - . , , , DI- .


, -. bravik.calendar.exporter.


$taggedServices = $container->findTaggedServiceIds('bravik.calendar.exporter');

, Reference , , ExporterManager, $exporters .


$exporterReferences = [];
foreach ($taggedServices as $id => $tags) {
    $exporterReferences[] = new Reference($id);
}

$exporterManagerDefinition->setArguments(['$exporters' => $exporterReferences]);

services.yaml ExporterManager:


bravik\CalendarBundle\Service\EventExporter\ExporterManager: ~

, .


(autoconfiguration)


services.yaml.


, 2 :


bravik\CalendarBundle\Service\EventExporter\Exporters\GoogleCalendarExporter:
    tags: ['bravik.calendar.exporter']
bravik\CalendarBundle\Service\EventExporter\Exporters\ICalendarExporter:
    tags: ['bravik.calendar.exporter']

:


App\Service\EventExporter\JsonExporter:
    tags: ['bravik.calendar.exporter']

, 3, 30 . .


, .

ExporterInterface.


№1. _instanceof


services.yaml :


_instanceof:
    # Apply tag to all ExporterInterface implementations
    bravik\CalendarBundle\Service\EventExporter\ExporterInterface:
        tags: ['bravik.calendar.exporter']

— !


App\Service\EventExporter\JsonExporter, .
, , . , .


№2. Symfony


, DependencyInjection/CalendarExtension load():


 public function load(array $configs, ContainerBuilder $container)
{
    $container->registerForAutoconfiguration(ExporterInterface::class)
        ->addTag('bravik.calendar.exporter');

   //...
}

Symfony , , .


, ExporterManager. :


# Register all EventExporter classes as injectable services
bravik\CalendarBundle\Service\EventExporter\:
    resource: '../src/Service/EventExporter/*'

.



Symfony, , . Symfony: , , Compiler Pass .


4-extend.


, , Symfony .


يمكنك القراءة عن بعض الأمثلة الأكثر تقدمًا لإعادة تعريف الخدمات واستخدام الأسماء المستعارة للخدمة لإنشاء نقاط امتداد:
( https://symfonycasts.com/screencast/symfony-bundle/override-service#play )


مقالات أخرى في السلسلة:


الجزء 1. الحد الأدنى للحزمة
الجزء 2. نأخذ الشفرة والقوالب في الحزمة
الجزء 3. تكامل الحزمة مع المضيف: القوالب ، الأنماط ، JS
الجزء 4. واجهة لتوسيع الحزمة
الجزء 5. المعلمات والتكوين
الجزء 6. الاختبار ، التطبيق الجزئي داخل الحزمة
الجزء 7 دورة الإصدار والتثبيت والتحديث


All Articles