We are building a Symfony2 application that will serve different sections using subdomains:
api.tld.com - API system
docs.tld.com - Documentation
assets.tld.com - System for serving images
How we are doing this is creating an app directory for each subdomain, and keeping the standard /app directory in place as the central shared config. There is also a custom bootstrap in the web directory for each app. Subdomains are routed accordingly using .htaccess.
The problem I am having is where multiple config files come in, particularly when they have their own routing imports. In some cases, there can be up to 4 configs.yml files. Take the following URL for example:
http://testing.docs.tld.com
The config setup currently works like this (and it works)
tld.com - Global config located at /app/config/config.yml
testing - Environment config located at /app/config/config_testing.yml. This config also imports config_dev.yml in the same directory.
docs - App config located at /app_docs/config/config.yml
These are all imported in the AppKernal in /app_docs/AppKernal.php:
// Load Global Configuration
// ROUTES INSIDE THIS CONFIG ARE NOT BEING LOADED
$loader->load(__DIR__.'/../app/config/config.yml');
// Load Environment Configuration
// ROUTES INSIDE THIS CONFIG ARE NOT BEING LOADED
$loader->load(__DIR__.'/../app/config/config_' . $this->getEnvironment() . '.yml');
// Load App-centric Configuration
$loader->load(__DIR__.'/config/config.yml');
Now the configs load just fine. But what I'm having trouble with, and not found any definitive documentation on, is when more than one of these configs define framework: router: resources. In the above example configs, these are loaded (attempted to anyway) as follows:
/app/config/config.yml
framework:
secret:%secret%
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: %kernel.debug%
/app/config/config_testing.yml
// No special Routing
/app/config/config_dev.yml
framework:
router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }
/app_docs/config/config.yml
framework:
secret: %secret%
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: %kernel.debug%
All of the configs are loading fine. But what I found is that only the last routing file called above is being included. So I assume the rule is that they are overriden as a rule, rather than extended.
So what I have spent the last couple of days trying to find out is, is it possible to extend the inclusion of routing files within config files in the fashion above? Another option I investigated was to find a way to import routing files in the AppKernal files. I was only able to find this, which doesn't explain exactly at what point this should be used (or where). It doesn't work within the AppKernal where the configs are included, so I assume the Router is not active at that stage.
Anyone have any ideas? I'd be very grateful.
I had the same need so we did like this:
/apps/config
/apps/config/common_config.yml
/apps/config/common_routing.yml
/apps/config/...
/apps/myapp1
/apps/myapp1/myapp1Kernel.php
/apps/myapp1/...
/apps/myapp1/config
/apps/myapp1/config/config.yml
/apps/myapp1/config/routing.yml
/apps/myapp1/config/...
/apps/myapp2
/apps/myapp2/myapp1Kernel.php
/apps/myapp2/...
/apps/myapp2/config
/apps/myapp2/config/config.yml
/apps/myapp2/config/routing.yml
/apps/myapp2/config/...
...
And in each app's yml file, we had:
/apps/myapp1/config/config.yml
imports:
- { resource: "../../config/common_config.yml" }
And then, you have to reproduce the same way in /web
/web/myapp1/app.php
Who will be calling your app
$kernel = new myapp1Kernel('prod', false);
$kernel->loadClassCache();
Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Related
I would like to exclude fields when exposing my API from my user class that extends FOSUser.
I've setup JMS Serializer on the global config file and created a FOSUB config to only expose the fields I need.
Global Config:
app/config/config.yml
jms_serializer:
metadata:
directories:
FOSUB:
namespace_prefix: "FOS\\UserBundle"
path: "#AppBundle/Resources/config/serializer/fos"
FOS config file:
src/AppBundle/Resources/config/serializer/fos/Model.user.yml
FOS\UserBundle\Model\User:
exclusion_policy: ALL
properties:
id:
expose: true
email:
expose: true
roles:
expose: true
This config is working perfectly on my local machine however it doesn't work when deployed on prod. Both use same stack, my guess is that on prod somehow the serializer can't find FOS config file.
Any help would be much appreciated.
The issue was somehow related to the naming of the config file.
While in local (macos) the file name Model.user.yml was working, in production (centos) it didn't work. So I had to rename the file to Model.User.yml then it worked fine on both.
I tried to find some documentation related to this issue but couldn't find any.
Take away: Make sure that the config file name represent exactly the entity you want to override.
Recently I've been working on improveing my vagrant enviroment and I've stumbled upon Running the Symfony application on Vagrant without NFS below 100ms blog post.
I've moved the vendor dir outside the VM shared directory, as suggested, by createing /tmp/app/vendor dir inside the VM and setting
export COMPOSER_VENDOR_DIR=/tmp/app/vendor
export COMPOSER_BIN_DIR=/tmp/app/bin
export SF2_ENV=vagrant
enviroment variables before running composer install.
Now, with vendors correctly installed to another path, I've modified the app/autoload.php file to detect if the app is running inside the VM by looking for the SF2_ENV enviroment variable:
if (array_key_exists('SF2_ENV', $_SERVER) && $_SERVER['SF2_ENV'] === 'vagrant') {
// vagrant enviroment detected
$loader = require sys_get_temp_dir().'/app/vendor/autoload.php';
} else {
// default
$loader = require __DIR__.'/../vendor/autoload.php';
}
This worked fine for one project, however on another project I kept getting the
PHP Fatal error: Cannot redeclare class Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry in /var/www/public_html/vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity/MappedSuperclass/AbstractLogEntry.php on line 13
error when trying to initialize the app cache php app/console cache:clear -e=prod.
Why was this happening?
Note: I've anwsered myself, as this is a Q&A style question (a note to my future self).
I am posting this as a reminder to my future self or anyone else interested. The problem was becouse in the second project I used Gedmo library and in my config.yml I defined:
doctrine:
orm:
entity_managers:
default:
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
mappings:
gedmo_translatable:
type: annotation
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable
is_bundle: false
So, the problem was clearly the %kernel.root_dir% part, which was hardcoded.
Solution
I've simply changed it to %vendor_dir% and defined this parameter in my parameters.yml - for production as vendor_dir: '%kernel.root_dir%/../vendor' and for local (dev) as vendor_dir: /tmp/app/vendor.
I already have problem with symfony2 project on Vagrant. But I resolve this without change location of /vendor directory.
Just disable the nfs share and locate your projects directly on /var/www
you can use this on vagrantFile :
config.vm.synced_folder '.', '/vagrant', disabled: true
Work with your Vagrant as like you work with a remote server...
What happening when you deploying in production environment your autoload.php file ? it's not very useful to change this only for dev environment (I don't speak only for this file but general idea).
How to setup a different configuration parameters file for each environment?
At the moment parameters in parameters.yml are used in both dev and prod environment, but I need different parameters in order to deploy my app in prod.
You can put all the parameters used in your dev environment in a app\config\parameters_dev.yml file (you need to create it) and then import it in your app\config\config_dev.yml:
imports:
- { resource: config.yml }
- { resource: parameters_dev.yml }
So when you work in local any parameter used in production will be overwritten by the new file with the right parameters.
And remember to Clear the cache!
I'm new to Symfony and a little confused by the imports key found at the top of config.yml. I am trying to import /our_stuff/admin/version.yml into Symfony's config.yml file.
This is what my config.yml file looks like:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: '/our_stuff/admin/version.yml' }
This is what I have inside my version.yml file
version:
last_recorded_software_version: '10.12.1'
But this produces the error:
FileLoaderLoadException: Cannot import resource "/our_stuff/admin/version.yml" from "/our_stuff/admin/symfony/app/config/config.yml". (There is no extension able to load the configuration for "last_recorded_software_version" (in /our_stuff/admin/version.yml).
Looked for namespace "last_recorded_software_version", found "framework", "security", "twig", "monolog", "swiftmailer", "assetic", "doctrine", "sensio_framework_extra", "web_profiler", "sensio_distribution")
To test, I've also moved the version.yml file into Symfony's config folder. The path is symfony_root/app/config/, but this still produces the same error.
Why does importing work for the default YAML files that are included in Symfony, but not the one's I include?
EDIT Edited for clarity
Edit 2 Here is the entirety of the /our_stuff/admin/version.yml file:
# Update this variable ONLY RIGHT BEFORE creating a new numbered release
version:
last_recorded_software_version: '10.12.1'
Edit 3 The solution:
The version.yml file needs to have a namespace of parameters in order to read them in the config.yml file
# app/config/config.yml
imports:
- { resource: 'parameters.yml' }
- { resource: '/etc/sites/mysite.com/parameters.yml' }
#/etc/sites/mysite.com/version.yml
parameters:
some_key:
some_other_key: value
some_other_key1: value
...
You can store your configuration files outside the project direcoty or in project directory and can include check this link global-configuration-files
You can include you configuration file like this:
# app/config/config.yml
imports:
- { resource: 'parameters.yml' }
- { resource: '/etc/sites/mysite.com/parameters.yml' }
Your version.yml file format should be:
parameters:
some_key:
some_other_key: value
some_other_key1: value
...
All config files in Symfony are parsed by Configuration component. Symfony application by default import only one file: config_%environment%.yml. This file has 3 predefined sections that have significant value for Symfony:
imports
Contain array of resources that will be imported by configuration component in processing. These resources may be xml, yml or even php files that will return array.
services
Contain service definitions that have very significant value for ServiceContainer that will create services from this config section.
parameters
Parameters that will have significant value for ServiceContainer that will manage all included values in parameters section of container. If you want to get parameters from service container you should define it here.
Also you can import any config file in your bundle's configuration class.
If you import your config files inside imports block or in your bundle's Configuration class you should place them in appropriate sections: parameters, services.
As was requested examples:
parameters.yml:
parameters:
param: value1
array: {key1: value2}
services.yml:
services:
class: FQCN/To/Your/Class
If you put your version.config under some bundle you have to import it like this :
- { resource: "#AAA/YourBundle/Resources/config/version.yml" }
Otherwise your first import will work perfectly :
- { resource: version.yml }
I followed the guideline on how to expose a semantic configuration for a bundle and configured it in my app/config.yml (through parameters.yml).
My bundle also contains some console commands. Right now this command either uses the dev or prod configuration, which is fine.
But how can I make the console commands use an additional configuration file that sets some things different than in config.yml?
E.g.
#app/config.yml
imports:
- { resource: parameters.yml }
foo:
view_mode: %view_mode%
and
#app/parameters.yml
parameters:
view_mode: 1
How can I make it e.g. use a different parameters.yml
#app/parameters_console.yml
parameters:
view_mode: 2
when called through the console? A new environment is not what I want here.
I think you need to create a custom environement
You just have to create a config_console.yml in your app/config folder and override the configuration you need.
imports:
- { resource: config_dev.yml }
foo:
view_mode: 2
Then in your application, just run
php app/console --env=console
This will run your application with default configuration of dev and with foo.view_mode = 2
You may want to note that it will create a new cache folder named console