Deploying symfony to Heroku, get swiftmailer parameters via configvars - symfony

I have deployed my symfony app to Heroku, but I want to configure the swiftmailer component with config_vars provided by Heroku. I already have two of them:
SYMFONY_ENV: prod
CLEARDB_DATABASE_URL: my-connection-string
Now what I would like to do is to decribe swiftmailer credentials in the config_prod.yml:
#config_prod.yml
swiftmailer:
transport: "%env(mail_transport)%"
host: "%env(mail_host)%"
username: "%env(mail_user)%"
password: "%env(mail_password)%"
spool: { type: memory }
I, then, set up the config_vars on Heroku, however when trying to deploy the app I got the following exception.
[Symfony\Component\DependencyInjection\Exception\EnvParameterException]
Incompatible use of dynamic environment variables "mail_transport" found in parameters.
[Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]
Unable to replace alias "swiftmailer.mailer.default.transport.real" with actual definition "%env(mail_transport)%".
[Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
You have requested a non-existent service "%env(mail_transport)%".
Script Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache handling the symfony-scripts event terminated with an exception
If I hardcode the parameters in the config.yml then deploying to Heroku succeeds.
What am I messing up? Thx in advance.

I do not know much about heroku but i know how to get ENV_VAR inside symfony config ;)
inside app/config where your other configs files reside create a new file called parameters.php
<?php
if(isset($_SERVER['AWS_MAILER_HOST']) ){
$container->setParameter('mailer_transport', #$_SERVER['AWS_MAILER_TRANSPORT']);
$container->setParameter('mailer_host', #$_SERVER['AWS_MAILER_HOST']);
$container->setParameter('mailer_username', #$_SERVER['AWS_MAILER_USERNAME']);
$container->setParameter('mailer_password', #$_SERVER['AWS_MAILER_PASSWORD']);
$container->setParameter('mailer_port', #$_SERVER['AWS_MAILER_PORT']);
$container->setParameter('mailer_encryption', #$_SERVER['AWS_MAILER_ENCRYPTION']);
$container->setParameter('mailer_auth_mode', #$_SERVER['AWS_MAILER_AUTH_MODE']);
}
replace all 'AWS_MAILER_...' with your ENVIRONEMENT_VAR
Inside your app/config/config.yml put
imports:
- { resource: parameters.yml }
- { resource: parameters.php } <------------

Related

Exclude fields from FOSUserBundle using JMS Serializer working on dev but not on prod environment

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.

Why am I getting "Cannot redeclare class" on Symfony2 + vagrant + moved vendors optimalization setup?

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 use a different console configuration in Symfony

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

Symfony2 bundle configuration parameters

My team develops a very large e-commerce project. Up to now, we had something like 40 configuration parameters in that bundle and I didn't know their final relations nor had a way to structure them properly, so we ended up using the standard parameters structure in the app/config.yml file. But, somewhere along the way I decided to move the config to the semantic configuration structure - so I can validate it, have a clean structure, easily extend it by means of bundle inheritance and so on.
The problem is I can't import our bundle parameters to another bundle config, now.
Here's what I could do before:
(...)
parameters:
company.bundle.email.user: user#domain.com
company.bundle.email.pass: #MyBeAUtiFULpA55w0Rd!
(...)
swiftmailer:
(...)
username: %company.bundle.email.user%
password: %company.bundle.email.pass%
Here's what I'm trying to do now and it doesn't work at all:
(...)
company_bundle:
(...)
settings:
(...)
mailer:
(...)
user: user#domain.com
pass: #MyBeAUtiFULpA55w0Rd!
(...)
swiftmailer:
(...)
username: %company_bundle.settings.mailer.user%
password: %company_bundle.settings.mailer.pass%
(...)
Of course the company_bundle node contains the semantic configuration, processed by the DIC and defined in Company\Bundle\DependencyInjection\Configuration.php.
All I end up with for now is the following error:
[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]
You have requested a non-existent parameter "company_bundle.settings.mailer.user".
So the question is: how to make my bundle parameters accessible in another bundle configuration parameters (I've already taken care of including my bundle configuration always before the Swiftmailer bundle)?
NOTICE: Swiftmailer bundle configuration is shown here only for demonstration purposes, I want to be able to reuse my bundle parameters across some other bundles as well.
What's the motivation behind that?
Well I want our product to be configured by a person who doesn't know Symfony well - so she must be able to open our bundle config file and just tweak the parameters, which will then be used in some Symfony bundles we use. So I want all application configuration to be accessible in our bundle's semantic conf, since I'd want not to expose the whole configuration to that person (I've already divided everything into separate config files, one of them containing the configuration for our bundle, the rest - for all the other ones).
So, is what I'm asking even possible?
As the parameters are to be modified in each installation (they probably differ at least between development and production environments), so (as Sgoettschkes said in comment) external file is the best solution.
In Symfony2 by default place for such parameters is parameters.yml file located in app/config/ dir.
In standard installation you can find for example such entries:
parameters:
database_driver: pdo_mysql
database_host: 127.0.0.1
(...)
These params are used in config.yml this way:
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
(...)
So you can define your params (in parameters.yml):
parameters:
(...)
company_bundle_email_user: user#domain.com
company_bundle_email_pass: #MyBeAUtiFULpA55w0Rd!
and use them (in config.yml):
swiftmailer:
(...)
username: %company_bundle_email_user%
password: %company_bundle_email_pass%

Unable to import the routing in symfony

I am using the Jobeet tutorial.
I have configured the routing in app/confing file as follow:
EnsJobeetBundle:
resource: "#EnsJobeetBundle/Resources/config/routing.yml"
prefix: /
In EnsJobeetBundle routing it is defined as below:
EnsJobeetBundle_job:
resource: "#EnsJobeetBundle/Resources/config/routing/job.yml"
prefix: /job
When I am using the URL http://localhost/Symfony/web/app_dev.php/job/ I get the following error:
Cannot import resource "#EnsJobeetBundle/Resources/config/routing/job.yml"
from "C:\wamp\www\Symfony\src\Ens\JobeetBundle/Resources/config/routing.yml".
Make sure the "EnsJobeetBundle/Resources/config/routing/job.yml" bundle
is correctly registered and loaded in the application kernel class.
I have also registerd in appkernel file also as follow:
new Ens\JobeetBundle\EnsJobeetBundle(),
What may cause these errors?
In my case, when trying a production url I was getting this same error.
In app/AppKernel.php there is a condition that only considers 'dev' and 'test' environment:
if (in_array($this->getEnvironment(), array('dev', 'test')))
if your bundle should also be enabled in prod environment you should modify the condition:
if (in_array($this->getEnvironment(), array('prod', 'dev', 'test')))
This solved the error for me.

Resources