لنتحدث عن كيفية إيقاف النسخ واللصق بين المشاريع ونقل الشفرة إلى حزمة مكون إضافي symfony 5. يمكن إعادة استخدامها. ستؤدي سلسلة من المقالات التي تلخص تجربتي مع الحزم عمليًا إلى إنشاء الحد الأدنى من الحزم وإعادة صياغة التطبيق التجريبي إلى الاختبارات ودورة إصدار الحزمة.
عند تصميم حزمة ، تحتاج إلى التفكير في ما يجب أن يكون مغلفًا بداخلها ، وما الذي يجب أن يكون متاحًا للمستخدم. هل يجب أن تحتوي الحزمة على وظائف ثابتة أم يجب أن تكون مرنة وتسمح لنفسها بالتوسع؟ إذا كانت المرونة مطلوبة ، فأنت بحاجة إلى توفير بعض نقاط التكامل لتوسيع الحزمة ، واجهتها.
دعونا نحاول تقديم مثل هذه النقاط في تطبيقنا التجريبي. في هذه المقالة:
- ربط المنطق المخصص بحزمة
- وضع العلامات
- تمرير مترجم
- خدمات التكوين التلقائي
إذا لم تكمل البرنامج التعليمي باستمرار ، فقم بتنزيل التطبيق من المستودع وانتقل إلى فرع التكامل 3 .
تعليمات تثبيت وبدء المشروع في ملف README.md
.
ستجد النسخة النهائية من التعليمات البرمجية لهذه المقالة في فرع 4-تمديد .
مهمة
يحتوي التقويم على وظيفة تصدير الأحداث إلى GoogleCalendar أو iCalendar.
مهمتنا هي جعل حزمتنا أكثر مرونة وإضافة القدرة لمستخدمي الحزمة لتوسيعها بتنسيقات التصدير الخاصة بهم في تطبيقاتهم.
على سبيل المثال ، أضف التصدير إلى ملف JSON. هيا بنا نبدأ.

كيف يتم تنظيم تصدير الأحداث؟
لفهم كيفية إضافة تنسيق جديد ، دعنا نرى كيف يعمل EventExporter .
يتم تنفيذ منطق التصدير في المكون EventExporter
الموجود في services/EventExporter
. لقد قمنا بنقلها بالفعل إلى الحزمة وقمنا بتصحيح أسماء مساحة الاسم. ملفات المكونات الرئيسية هي:
ExporterInterface
محاكاة تنسيق تصدير الحدث وExporterManager
,
ExporterInterface
.
— , ( Google Calendar), ( iCalendar). inline. EventController::export()
, .
,
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;
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 دورة الإصدار والتثبيت والتحديث