Make your Bundles a simple app without code
MIT License
Welcome to OneBundleApp, a small project to allow your bundle to be an app without any configuration.
Symfony environment is changing so much, and with it, the last movements are telling us, the community, that the Bundle idea, the concept, is losing its leadership. Symfony became what it is because of the components and the Bundles, and both elements should be treated the way they deserve.
In this case, we will give some love the the bundles. To your bundle. But first of all, let's talk about what is a bundle. Please, take in account that our conversation should always be "What a bundle is", and never "What a bundle is meant to be". The second is something important at the beginning of any project. The second is important in every real project. Let's talk about what bundles are and their behaviour in the ecosystem.
A Bundle is a layer. A layer that let us propose some classes to a Symfony project and giving these classes an specific purpose. The framework will, then, create these tools to make this business logic accessible from the console and the HTTP channel via the Request/Response pattern.
Good. But we will stay thinking about bundles, and we will not go away from this point.
A bundle is meant to be a package. A plugin. A bundle is meant to be an isolated package. But, and knowing the real ecosystem we have in front of us, is it really this isolated element it was meant to be?
Not. At all.
The package Symfony Bundle Dependencies was created some time ago in order to cover these dependency needs. A bundle, as a PHP package should define the dependencies in an existence way (composer) and in an executable way (Bundle). So the first step was covered by adding this simple layer to your bundles. Each bundle will return an array of Bundle instances or namespaces to define ... To be instanced, I need these other bundles to be instanced first.
Remember the change from Symfony 2.0 and 2.1? Do you remember the old .deps file? Well. This is exactly the same. Exactly the same!
After this movement, your kernel should only have these bundles you specifically want to instantiate. If your bundle then needs other bundles, required by composer previously, then these bundles will be instantiated properly by the library.
Ok. First layer solved.
Continuing talking about what a Bundle is... should a bundle itself be enough to be operative? A bundle contains enough information to make itself runnable without any other layers... so should be a bundle information something http-ready and console-ready?
Well, the answer is yes.
If my bundle has self-defined commands, self-defined controllers (PHP end-points and a routing.yml file), then nothing else is needed to make it accessible from both point of entry.
The second question is then a natural one. Should all bundles be useful in an isolated way? Not at all. Tels list some examples.
If your case is not recommended, please keep using the Symfony application. Otherwise, if you have a Bundle that should be playable without extra things... You're lucky then. Let's see how to do it.
Let's divide the game in three steps.
The installation. We need to require the library that will transform your bundle into an application. That simple.
To do that, open your composer.json file and merge these lines with your current composer definition.
"require": {
"one-bundle-app/one-bundle-app": "dev-master"
},
"scripts": {
"post-install-cmd": [
"OneBundleApp\\App\\ComposerHook::installEnvironment"
],
"post-update-cmd": [
"OneBundleApp\\App\\ComposerHook::installEnvironment"
]
}
By using installEnvironment static method you will install all the environment. You can install parts of this environment
"scripts": {
"post-install-cmd": [
"OneBundleApp\\App\\ComposerHook::installConsole",
"OneBundleApp\\App\\ComposerHook::installReactServer",
"OneBundleApp\\App\\ComposerHook::installWebServer",
],
// ...
}
bin/console
withbin/server
withweb
folder.In that case, you will download the package one-bundle-app/one-bundle-app
and,
after installing or updating, some files will be copied in order to become an
application following the Symfony app style.
Then make a composer update
.
Then we have the configuration. We need to tell the bundle we want to use for
the application and some extra configurations, if we need them. The basic, the
app.yml
file. Super simple an fast.
# app.yml
bundles: MyBundle\MyBundle
config:
parameters:
some: blabla
routes:
- '@MyBundle/Resources/config/routing.yml'
You can specify an extra configuration per each environment, by appending it in the file.
# app_dev.yml
bundles:
- MyBundle\MyBundle
- Symfony\Bundle\WebServerBundle\WebServerBundle
config:
parameters:
some: anotherblabla
Some advices here.
After the composer update, the system will create these elements in your bundle root.
/var
folder, where to add cache, sessions, logs.../web
folder, with two files. The HTTP entry points app.php and the/bin
folder, with one file. The console entry point console. ThisThat should be enough. Then your bundle should be accessible both from console and the HTTP layer. Use an Apache or an Nginx, or even the command bin/console server:run without any extra configuration.
By using the ReactPHP Server, you'll be able to provide a nice endpoint by using a persistent Symfony kernel, always hosted in memory, and with all needed services already built.
Make sure you have configured the project to have a server installed
"scripts": {
"post-install-cmd": [
"OneBundleApp\\App\\ComposerHook::installReactServer",
],
}
After that, you'll be able to initialize the server by just doing
bin/server 0.0.0.0:8888
0.0.0.0
means localhost, but accessible from everywhere.prod
. You can changebin/server 0.0.0.0:8888 --dev
false
. You can changebin/server 0.0.0.0:8888 --debug
bin/server 0.0.0.0:8888 --dev --debug
You can use as well the PPM server if you need to have a little bit more workers availability (for example if you have some long-term processes mixed with short-term processes).
You can check PHP PM Project documentation of how to start the server. This repository has specific bridge and adapter classes to work properly and only with this integration.
vendor/bin/ppm start --host=0.0.0.0 --port=8888 \
--workers=3 \
--bootstrap=OneBundleApp\\PPM\\Adapter \
--bridge=OneBundleApp\\PPM\\Bridge \
--app-env=prod \
--debug=0 --logging=0