Let's talk about how to stop copy-paste between projects and transfer the code to a re-usable symfony 5 plug-in bundle. A series of articles summarizing my experience with bundles will lead in practice from creating a minimal bundle and refactoring a demo application to tests and the bundle release cycle.
In the previous article, we created a minimal bundle of two files and included it in the project.
In this article:
- Porting code to bundle
- Dependency Injection: registering bundle services in a DI container
- Migrating controllers and setting up routing
- Resource Path Determination Mechanism
- Transferring templates to bundles
If you are not completing the tutorial sequentially, then download the application from the repository and switch to the 1-bundle-mockup branch .
Instructions for installing and starting the project in a file README.md
.
You will find the final version of the code for this article in the 2-basic-refactoring branch .
Let's proceed to refactoring.
We move the main files
A bundle can contain everything the same as regular Symfony applications: entities, controllers and commands, templates, assets, tests and any other code.
, , bundles/CalendarBundle/src
( ):
# Crate dirs
cd bundles/CalendarBundle/src/
mkdir Controller Entity Service
cd ../../../src
# Move files
mv Form Repository ../bundles/CalendarBundle/src/
mv Controller/EditorController.php Controller/EventController.php ../bundles/CalendarBundle/src/Controller
mv Entity/Event.php ../bundles/CalendarBundle/src/Entity
mv Service/EventExporter ../bundles/CalendarBundle/src/Service/EventExporter
mv Twig ../bundles/CalendarBundle/src/Twig

, . namespace
use
App\
bravik\CalendarBundle\
.
App\
: .
IDE .
IDE PhpStorm Ctrl/Cmd + Shift + R
.
use App\Repository\EventRepository
SiteController

.
:

SiteController
: EventRepository
. autowiring Symfony typehints DI-.
src/Services
, .
Dependency Injection
, DI- , .
, .
, Symfony- services.yaml
, DI-.
src
config/services.yaml
:
parameters:
#
services:
#
_defaults:
#
# typehints ( )
# https://symfony.com/doc/current/service_container.html#the-autowire-option
autowire: true
# :
#
# https://symfony.com/doc/current/service_container.html#the-autoconfigure-option
autoconfigure: true
# DI-
bravik\CalendarBundle\Repository\EventRepository: ~
bravik\CalendarBundle\Controller\EventController: ~
bravik\CalendarBundle\Controller\EditorController: ~
3 .
- config/services.yaml
, .
@todo
:
# Twig
bravik\CalendarBundle\Twig\TwigRuDateFilter: ~
# EventExporter DI-
bravik\CalendarBundle\Service\EventExporter\:
resource: '../src/Service/EventExporter/*'
# ExporterProvider DI-
# 2
bravik\CalendarBundle\Service\EventExporter\ExporterManager:
arguments:
$exporters:
- '@bravik\CalendarBundle\Service\EventExporter\Exporters\GoogleCalendarExporter'
- '@bravik\CalendarBundle\Service\EventExporter\Exporters\ICalendarExporter'
, , . , . src
DependencyInjection/CalendarExtension.php
:
<?php
namespace bravik\CalendarBundle\DependencyInjection;
use Exception;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
class CalendarExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
}
}
. <BundleName>Extension
, src/DependencyInjection
Symfony\Component\DependencyInjection\Extension\Extension
.
Symfony DI-, Extension-. , Extension::load()
.
, . , PHP-. .
services.yaml
:
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader(
$container,
new FileLocator(__DIR__.'/../../config')
);
$loader->load('services.yaml');
}
, :

.
Symfony :
config/routes.yaml #
config/routes/annotations.yaml # ,
#
. annotations.yaml
:
controllers: #
type: annotation #
resource: ../../src/Controller/ # ,
: config/routes.yaml
.
calendar_routes:
type: annotation
resource: '../src/Controller/'
config/routes/annotations.yaml
.
:
calendar_bundle:
resource: '@CalendarBundle/config/routes.yaml'
.
@CalendarBundle
β .
Symfony .
, /admin
- : /admin ?
, :
calendar_bundle:
resource: '@CalendarBundle/config/routes.yaml'
prefix: /admin
name_prefix: cms.
security
. , .
, Symfony vendor_name_
. .
, Twig «» .
:
@<BundleName>Bundle/path/to/config
β@<BundleName>/path/to/template
β .
Symfony Β« Β». . .
./src
. , Symfony 4 src/Resources
. 4 Symfony , β . , .
CalendarBundle
getPath()
:
public function getPath(): string
{
return dirname(__DIR__);
}
@CalendarBundle
.
, !

? .
. , , -.
templates
templates/event
:
mkdir bundles/CalendarBundle/templates
mv templates/event/* bundles/CalendarBundle/templates
β , . .
Β« Β» IDE . event/
@Calendar/
.

@Calendar
Twig , namespace Twig. templates
, Symfony namespace, templates
Resources/views
( ).
site/index.html.twig
twig-. :

, β .
: base.html.twig
-:
{% extends 'base.html.twig' %}
.
, , DI-. Example Project 2-basic-refactoring.
- , β namespace .
App
- , β Extension-. DI- . , .
- . . .
- , , .., «» , . .
, JS -.
:
1.
2.
3. : , , JS
4.
5.
6. ,
7. ,