Split my Symfony 4 application
Split my Symfony 4 application into multiple libraries
Recently at work I had to split the code of one of our Symfony application for multiple reasons. But because Symfony 4 is Bundle-less, I had to find an other way to split.
A quick tour of my existing project
Initially I had my files organized by following the best practices of Symfony. It looked like this :
.
├── composer.json
├── config
├── src
│ ├── Command
│ │ ├── Part1
│ │ └── Part2
│ ├── Controller
│ │ ├── Part1
│ │ └── Part2
│ ├── Entity
│ │ ├── Part1
│ │ └── Part2
│ ├── Repository
│ │ ├── Part1
│ │ └── Part2
│ └── Service
│ ├── Part1
│ └── Part2
└── templates
As you can see, all the code is already spited but there are many issues :
- the files are not totally spitted they just leave next to each other
- there is often a merge conflict on the configuration files
- I can't remove easily one part of my project
- the dependencies are all mixed together (unique
composer.json
, ...)
Moving the files
So I've created a new folder libraries
, and I'll put all my libraries in it. It looks like that:
.
├── composer.json
├── config
├── libraries
│ ├── Part1
│ │ ├── config
│ │ ├── src
│ │ │ ├── Command
│ │ │ ├── Entity
│ │ │ ├── Repository
│ │ │ ├── Service
│ │ │ └── composer.json
│ └── Part2
│ │ ├── config
│ │ ├── src
│ │ │ ├── Command
│ │ │ ├── Entity
│ │ │ ├── Repository
│ │ │ ├── Service
│ │ │ └── composer.json
├── src
│ ├── Controller
│ │ ├── Part1
│ │ └── Part2
└── templates
This migration is quite easy. You just have to move the files and update the namespace
to match the new tree structure. For example, this old command:
<?php
namespace App\Command\Part1;
public class MyCommand {}
Will became :
<?php
namespace Part1\Command;
public class MyCommand {}
In each composer.json
of the libraries, I've put the exact dependencies for the concerned librairy.
Here is the composer.json
for my part1 library :
{
"name": "my-project/part1",
"description": "A library to do awesome things",
"type": "library",
"license": "proprietary",
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Part1\\": "src/"
}
},
"require": {
"php": "^7.1.3",
...
},
...
}
Then the composer.json
at the root of my project is almost empty, I just have to import my brand new libraries :
{
"name": "my-project/core",
"type": "project",
"license": "proprietary",
"require": {
"my-project/part1": "*@dev",
"my-project/part2": "*@dev",
},
"repositories": [
{
"type": "path",
"url": "libraries/*"
}
],
...
}
The magic happen in the repositories
section. It said that there are new libraries in my library
folder.
Then we need to configure our Symfony application !
Update the Symfony configuration files
Like I said in the beginning of this post, I want to separate my configurations, so I can remove the old ones quite easily. In my config/packages/
folder I've add a part1.yaml
and a part2.yaml
file which define all the configuration for my lib. For example here is my part1.yaml
:
services:
Part1\:
resource: '%kernel.project_dir%/libraries/part1/src/*'
exclude: '%kernel.project_dir%/libraries/part1/src/{Command,DataFixtures,DependencyInjection,Entity,Migrations,Repository,Tests,Kernel.php}'
autowire: true
# I have to redefined all that things, otherwise our application can't see them
Part1\Repository\:
resource: '%kernel.project_dir%/libraries/part1/src/Repository/*'
autowire: true
tags:
- 'doctrine.repository_service'
Part1\DataFixtures\:
resource: '%kernel.project_dir%/libraries/part1/src/DataFixtures/*'
autowire: true
tags:
- 'doctrine.fixture.orm'
Part1\Command\:
resource: '%kernel.project_dir%/libraries/part1/src/Command/*'
autowire: true
tags:
- 'console.command'
# Then overload the services you need, here it's for doctrine but you can do it for everything
doctrine:
orm:
mappings:
Part1:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/libraries/part1/src/Entity'
prefix: 'Part1\Entity'
alias: Part1
I've left the Controllers in my main src/
folder because for me belong here. And that's it ! Your application is now really spitted.