Symfony bundle configuration - php

I've just started working with Symfony and have run into a problem that I'm having a hard time tracking down information about.
I'm trying to create a bundle which has its own configuration file, e.g. configuration for doctrine connections.
All documentation I've found have never mentioned of showed how this can be set. Is it possible?
What I want to solve:
I have a bundle which when installed should handle connection to a secondary database table without any configuration needed from the main application in which the bundle has been integrated. Ultimately the configuration in the bundle should be override-able from the main application.
The bundle should be in the lack for a better work "self contained".
I've found documenation about bundle configuration. But all I've seen mentioned there is if one would like to configure the bundle and not interaction with other components (might have missed something).
tl;dr I want to have a config (e.g. AppBundle/Resources/Config/config.yml) file inside a bundle which can configure things like doctrine.
What i've tried
I've tried placing the configuration inside a config.yml file located in Resources/Config/. But I guess the file is never read.

I think it is not good idea to put something related to configuration right inside your bundle and ruin it's reusability by doing such thing. As far as I understood your task what your really need is to configure second entity manager to manage entities from secondary database when you need them. Same problem and its solution are described in following question: Doctrine 2 - Multiple databases configuration and use
Hope that will help!

Related

Symfony 2/3 Get Classes in Directory that Implement an Interface

Is there a nice way in Symfony 2 or 3 to load all classes within a directory that implements a particular interface?
Since Symfony 3.3/3.4 it is possible by using configuration only (without a need to write custom CompilerPass):
# config/services.yaml
services:
# ...
_instanceof:
App\HandlerInterface:
tags: ['app.handler']
App\HandlerCollection:
# inject all services tagged with app.handler as first argument
arguments: [!tagged app.handler]
and if you need to restrict services to register from a single directory see importing with resource
references:
https://symfony.com/doc/current/service_container/3.3-di-changes.html#auto-configure-with-instanceof
https://symfony.com/doc/3.4/service_container/tags.html#reference-tagged-services
http://symfony.com/doc/3.4/service_container.html#importing-many-services-at-once-with-resource
Short answer is: you can't.
You don't know, what is in a file until you load it.
Long answer (taking into account what you have wrote in the comment under the question):
The only thing you know before you load a file is its name. So one of solution is to name your modules' classes (and files) with a fixed pattern like UserModule, ProductModule and so on. That way you can load all modules by their names. But this is the solution that I wouldn't suggest.
I my opinion you should change the approach and inverse the workflow. Create a class in which you will define all modules that need to be loaded. In Symfony it's called by default AppKernel, in which you define bundles (modules) to be loaded and initialized.
This has a few advantages.
You can have multiple entry points to your application and configure each one with different modules.
You may have a few different environments (like production and development) with different modules loaded in both of them. (e.g. add some modules in development like profiler)
Also dependency managment is much easier, since you can load defined modules and add their dependencies also with autoloading.
In general I think that you should avoid manual loading any php files (except autoload.php or similar that contains autoloaders) at all.

Loading second app into its own namespace - which database will it use?

As the subject says, really.
Assume I have two apps, namespaced as App_A and App_B. App_A has App_B imported as a git submodule and then autoloaded via its composer.json.
When I call App_B\SomeModel->someMethod() from an App_A controller, will the model query the database configured in App_B's config files, or will it inherit the config values from App_A?
Short answer: it won't inherit App_B's config files.
Expanded answer: App_A is loaded with it's config files. You call App_B\SomeModel::someMethod() from App_A, App_A's configuration will be used. To have two independent applications with 'knowledge' of each others state you would need to define a communication method between the two such as Message Queues(MQ), HTTP, Sockets, Streams etc etc. You would also never import App_B as a submodule of App_A and vice versa unless you're ok with App_*'s classes being used in the context of the loaded application stack.
Another option is to look at the HMVC or Heirarchical MVC pattern. This could possibly give you a solution to this problem without keeping the applications separate. There was a bundle in Laravel 3 enabling HMVC but I haven't looked into it since then as it (imo) is an anti-pattern. I don't know if one exists for Laravel 4 or 5.

Symfony Routes without app/config/routing.yaml

The tutorials I've read for Symfony 2 instructs users to enter their routing information in
app/config/routing.yml
If users want to have routing information in their own bundles, they're instructed to add a routing.yml file to their Bundle, and then point to their file from app/config/routing.yml with something like
my_route_stuff:
resource: "#CustomstuffBundle/resources/config/routing.yml"
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file? I'm looking for the ability to hand off a bundle to someone else, and have them be able to deploy it into their Symfony application without needing to edit their own app/config/routing.yml.
If this isn't possible, bonus point if anyone can explain why (i.e: the general philosophy behind) routing information is part of the AppKernel instead of the individual Bundles. I'm still a little unclear on the differences between routing.yml files and the normal Symfony config.yml files.
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file?
No, this is the way SonataAdminBundle, FOSUserBundle and a bunch of others handle it.
Why?
Routing belongs to the application, not each and every bundle. If every bundle started including their own routing files and Symfony2 autoloaded them, you would quickly have a mess of routes you may or may not want to enable in your application.
What if SonataAdminBundle wanted you to use /admin, but you already had a route there and wanted Sonata to use /sonata/admin instead? You'd need a file to override those routes and then you're back to square one!
Additionally, although caching mitigates this part, looking up files is expensive and would significantly slow down the development environment. This is why translation files are read from cache even in dev mode and you must clear the cache when you add a new translation resource. See: http://symfony.com/doc/current/book/translation.html#message-catalogues
Finally, leaving the routing out of config.yml is simply a matter of organization. Routing and configuration are two different things and don't belong in the same file.
The general idea is that every file is a thing and should only do that thing.

Cleaning a Symfony project and installing a new bundle

Im very new to Symfony, yet Im already familiar to the MCV model, after a while reading the documentation I have now the standard edition of Symfony 2 running on my server.
Fresh start
As you know Symfony comes with a hello world app and some welcome scripts, how can I clean all of that?, even better, is there a way to install a Symfony project without the examples bundles?
Data base structure restore
In the past, every time I developed an app with database, I created the structure of the tables using phpmyadmin and then an initial php script that restore that database if I need to install my app on other server. Working with Symfony is quite different, I read that it use doctrine and the Symfony core restore the database format using some internal files. I have a bundle that I need to install, I know that this bundle/app use MySQL, I set the config file with all my MySQL information but I dont know how I can run a sript that will restore a clean database needed for that particular app. I know it has something to do with php app/console schema:update but not so sure.
Thanks for any orientation.
how can I clean all of that?, even better, is there a way to install a Symfony project without the examples bundles?
There is no way to do that in Symfony2 and it looks like it never become a part of the Symfony2 project:
"I think that we need clear instructions on how to remove the Acme demo code by hand. I'm -1 on added a CLI command to do that automatically."
-- fabpot on github
The things you should do:
Remove the src/Acme directory
Remove $bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); (line 25) in app/AppKernel.php
Remove the related routes from app/config/routing_dev.yml (_welcome, _demo_secured and _demo)
You can remove everything in the security: key in app/config/security.yml and place enabled: false in it. However, this isn't needed and it works like a nice boilerplate for your own security
Your other question: Symfony2 don't have a 'view' layer. You can choose to use whatever you want. But Symfony2 included 2 ORMs in their framework by default, Doctrine and Propel. You can read more on how to work with these libraries in the documentation: Doctrine and Propel.

How should I structure my application?

I understand that this question may be vague, I will try my best to explain my problem and hopefully can get lots of insights from the experienced and hopefully this will not be closed.
I'm writing a PHP web app framework based on Symfony 2's components and bundles, my question may not relate to that however. The framework is intended to be open to 3rd party plugins, these plugins will have their own config files (yaml) and the person who install these plugins should be able to override these settings locally.
I also have to make sure that each time the person perform the plugin upgrade operation, it should be easy to loop over the list of "upgrade patches" to upgrade the plugin's settings while still retaining the local settings.
I imagine I can have a local, app's specific plugins.yml file which store something like this:
pluginA:
somesettings: value
somesettings2: value2
This app's specific settings file will allow user to override any default settings. And then each plugin can contain an "upgrade" class that will contain all the patches for each version, the framework will identify the current installed path and will loop through each "upgrade patch" and perform actions until it reach the most current version.
Does this sound like a good option, or if there is something else I should look into? How do I have configuration settings that can be overridden can be upgraded easily? Please let me know if you need more details.
It seems to me that you are looking to achieve something that actually core Symfony allows to do - i. e. to let other users override / implement custom parts of an already existing bundle.
If so, maybe this answer can give a good idea on how to achieve that using the ClassLoader Component (Symfony 2.0) or Composer (Symfony 2.1):
How can I override Core Symfony2 Classes?

Categories