Symfony2 - creating own vendor bundle - project and git strategy
We're considering creating our own common
bundle for entity mapping and services for use within few separate apps. A bundle should be easy to modify, run, include and test. I know about Best Practices for Structuring Bundles, but I don't know what git
strategy to use when it comes to development.
Should we create common
bundle as a whole project and commit whole repository to our git server, or is it better to start source control only for root of common
bundle and push only its contents? I see this approach in bundles available on github
, but I don't know easy and comfortable way to develop bundles that way.
Solution 1:
Create a new empty symfony project
php composer.phar create-project symfony/framework-standard-edition demo/ 2.4.1
cd demo
Generate a new bundle
(for example src/Company/DemoBundle
)
php app/console generate:bundle
cd src/Company/DemoBundle/
Init your github repository in src/Company/DemoBundle
git init
touch README.md
git add .
git commit -m "initial commit"
git remote add origin https://github.com/YourAccount/DemoBundle.git
git push -u origin master
Add a composer.json file
src/Company/DemoBundle/composer.json
:
{
"name" : "company/demobundle",
"description" : "A demo bundle",
"type" : "symfony-bundle",
"authors" : [{
"name" : "demo",
"email" : "[email protected]"
}],
"keywords" : [
"demo bundle"
],
"license" : [
"MIT"
],
"require" : {
},
"autoload" : {
"psr-0" : {
"Company\\DemoBundle" : ""
}
},
"target-dir" : "Company/DemoBundle",
"repositories" : [{
}],
"extra" : {
"branch-alias" : {
"dev-master" : "some_version-dev"
}
}
}
Now you have the base structure of your bundle
Use it in another project
composer.json:
[...]
"require" : {
[...]
"company/demobundle" : "dev-master"
},
"repositories" : [{
"type" : "vcs",
"url" : "https://github.com/Company/DemoBundle.git"
}],
[...]
Do:
curl -sS https://getcomposer.org/installer | php
php composer.phar update company/demobundle
app/AppKernel:
new Company\DemoBundle\CompanyDemoBundle(),
Work on it
- You can clone your DemoBundle in the
src/Company
folder, then manually install it - You can use symlink
Conclusion
You can develop and test your bundle in your first project and use it with github and composer in your second project.
Solution 2:
An important point to know is that you can commit into your repo from the /vendor. Indeed, composer creates a second remote called "composer" for each bundle (or package) that references the repo of the package, in order you can work on it in a working context.
So the good practice is to register your package in your composer.json for all your projects and commit from your /vendor/MyCompany/MyBundle
, from any project.
As a proof, just run git remote -v
from any bundle in your vendor.
The bad practice would be to consider your bundle as a separate project and have symlinks with it. The main reason why this is the bad practice is that you won't be able to declare dependancies with your bundle. Moreover you'll have some difficulties with the deployment of your projects.
Solution 3:
In Symfony4, generate:bundle
command is no longer available. Instead, you may follow this tutorial.
First create a project with:
composer create-project symfony/website-skeleton my-project
Then, create a my-project/lib/AcmeFooBundle/src
directory. Here will live your bundle. The namespace for this directory will be Acme\AcmeFooBundle
, so if you create a service class at lib/AcmeFooBundle/src/Service/Foo.php
, its namespace would be Acme\AcmeFooBundle\Service
.
Now we need to tell composer autoloader to look for new classes at that new directory, so we need to edit composer.json
autoload
section:
"autoload": {
"psr-4": {
"Acme\\AcmeFooBundle\\": "lib/AcmeFooBundle/src/",
}
},
and run composer dump-autoload
.
Now you only need to add your bundle class to config/bundles.php
:
return [
...
Acme\AcmeFooBundle\AcmeFooBundle::class => ['all' => true],
];
and dependency injection to load configuration from your bundle.
If you want to check your services before adding dependency injection, you can just autowire them at config/services.yml
:
services:
...
Acme\AcmeFooBundle\Services\Foo: ~
That's all. Follow best practices and go on coding.
PS: I've published a post with a few tips for developing Symfony reusable bundles.