Setting parameters conditionally in symfony - symfony

Is there a way to set a parameter in symfony based on a certain condition, f.e. an ENV var?
Expression language came to my mind but it seems its only supported in arguments, properties and calls
config.yml:
parameters:
env(CI): false
ci: '%env(CI)%'
database_host: "#=parameter(ci) ? 'localhost' : 'mysql'"
doctrine:
dbal:
connections:
cms:
host: "%database_host%"
UPDATE
Expression language doesnt work in that case (Up to SF 3.3 currently) so i used Oli's approach which works:
get_params_from_env.php:
$container->setParameter('database_host', 'mysql');
if (getenv('CI')) {
$container->setParameter('database_host', '127.0.0.1');
}

Add this line to config.yml:
imports:
- { resource: get_params_from_env.php }
Then, in the php file, use this:
<?php
$container->setParameter('app.dummy_var', getenv('DUMMY_VAR'));
You can read about including your own PHP files here, under 'advanced techniques': http://symfony.com/doc/current/configuration/configuration_organization.html

Related

Symfony #Paramconverter works over autowiring

I am working on upgrade Symfony 3.3 to 4.4 and almost done with it, but I have one last issue.
I enabled autowiring with default config, but whole project uses lots of #ParamConverter conversions without annotation.
Problem: ParamConverter with auto_convert tries to convert services and classes that are mentioned to controller by typehinting for autowiring (not entities).
Controller:
/**
* #Route("/report", name="report_page")
*/
public function report(
Request $request,
FileManager $fileManager
): Response {
// code
}
Error:
The class 'App\Service\FileManager' was not found in the chain configured namespaces App\Entity.
Service 'App\Service\FileManager' exists and works correctly.
ParamConverter config (by default 'request: {converters: true, auto_convert: true}'):
sensio_framework_extra:
router:
annotations: false
Doctrine config:
doctrine:
dbal:
default_connection: default
connections:
default:
# config
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
Base:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: App\Entity
Controller setting (services.yaml):
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../src/*'
exclude: '../src/{DataFixtures,Entity,Objects,Repository,Utils}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
I understand that I can set 'sensio_framework_extra.request.auto_convert' to false and use #ParamConverter annotation everywhere in controllers, but there are too many places with this conversion and I try to get default behavior, so additional #ParamConverter annotations would be extra.
Just in case: I tried to disable auto_convert and everything worked correctly (services were autowired and entities were passed to controllers).
Also I checked that I installed last available versions of packages and bundles.
Need some hints on it. Probably I missed something. I tried to find exact way how ParamConverter works by default and how it checks that class is entity or not, but it is too complicated and I decided that I dug too deep.
EDIT:
Probably I have some issue with autowiring's config and not paramconverter. But I checked php bin/console debug:autowiring and got all needed services as available via autowiring.
It looks like symfony is trying to convert the fileManager like an entity.
Try moving the injected service(s) into the __construct method of the controller (and add the property to the controller) like:
private $fileManager;
...
public function __construct(FileManager $fileManager) {
$this->fileManager = $fileManager;
}
and then access it in the report method:
$this->fileManager

How to set _locale dynamically based on host

Is there any way to set _locale parameter of routing configuration as a function call or an expression result? I have multiple hosts running on the same symfony app, and there is an i18n turned on. Everything is working fine, but now i need to have another locales set for a specified host.
Right now my routing config looks like
app:
resource: '#AppBundle/Controller/'
...
requirements:
_locale: '%route_locales%'
...
and i have something like this in parameters:
...
route_locales: en|de|fr
...
That would be perfect if i can use something like
"#=service('AppBundle\\\\...\\\\LocalesConfigurator').getLocales()"
as a _locale: value to get this value based on a function call result. Or maybe there are some other options to get another _locale set for a specified host?
You can do it like #Jakumi suggested (via env params passed from server)
or using only application logic:
In route_locales put all possible locales that can be used in any host.
Validate incoming _locale inside "request listener" depending on request host - if some _locale is not allowed for host then return 404 response or show 404 error page etc.
Seems like i've found at least one solutuin, thanks to Jakumi for the idea. I've created a parameter in my config file, which receives an environment varaible. Then i use this parameter in my routing file. The main idea is that i can control this environment variable value using bootstrap file. So it looks like
bootstrap.php (in the example it's just a static value, but in a real life this value will depend on host).
bootstrap.php
...
$_SERVER['SYMFONY__ROUTE__LOCALES'] = 'en|es';
...
config.yml
parameters:
route_locales: '%route.locales%'
routing.yml
app:
resource: '#AppBundle/Controller/'
...
requirements:
_locale: '%route_locales%'
...
I don't realy like this solution, and will be thankful for any better solutions, but at least it does what i want.
I was in the same issue some months ago and I was able to found a solution that worked correctly, but there may also be some better ones.
As I needed different route names to be loaded depending on the locale (i.e. /contact in English and /contacto in Spanish) what I did was creating the methods in the controller and creating an individual link to them in routes.yaml
contact-en:
path: /contact/
controller: App\Controller\ContactController::index
host: domain1.tld
contact-es:
path: /contacto/
controller: App\Controller\ContactController::index
host: domain2.tld
Then I created an EventListener called LocaleSwitcher:
class LocaleSwitcher
{
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$host = $request->getHost();
switch($host) {
case 'domain1.tld': {
$request->setLocale('en');
break;
}
case 'domain2.tld': {
$request->setLocale('es');
break;
}
}
}
}
And then adding it in services.yaml for event kernel.request and priority 20:
App\EventListener\LocaleSwitcher:
tags:
- { name: kernel.event_listener, event: kernel.request, priority: 20 }

How to use JMSSerializerBundle with Gedmo Timestampable

I am using JMSSerializerBundle with Symfony3. I am using TimestampableEntity trait. What I want to achieve is to receive that trait with JMSSerializer.
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Gedmo\Timestampable\Traits\TimestampableEntity;
class Thread
{
use TimestampableEntity;
use SoftDeleteableEntity;
(...)
}
I have added metadata to the jms_serializer config like this:
config.yml
jms_serializer:
enable_short_alias: false # controls if "serializer" service is aliased to jms_serializer.serializer s
metadata:
directories:
- { path: "%kernel.root_dir%/Resources/Gedmo/serializer", namespace_prefix: 'Gedmo\Timestampable\Traits' }
\app\Reources:
Gedmo\Timestampable\Traits\TimestampableEntity:
exclusion_policy: ALL
properties:
created_at:
expose: true
But it is not working.
I know that I can configure it to use my Thread class and expose all necessary fields but I wonder if it is possible for traits.

FOSElasticaBundle & Propel

I have installed FOSElasticaBundle "friendsofsymfony/elastica-bundle": "^3.2"
(with symfony 2.8.8) and tried to define this simple configuration
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
indexes:
project:
types:
item:
mappings:
id: { type: integer }
itemno: { type: string }
persistence:
driver: propel
model: Model\Item\Item
provider: ~
Unfortunately I'm getting following error
The parent definition "fos_elastica.listener.prototype.propel" defined
for definition "fos_elastica.listener.project.item" does not
exist.
As I read through the documentation, there is no "listener" available for propel - that's why I'm a little bit confused about the error message. I already tried to define the missing definition, but with no result.
Is it necessary to define any class/service as provider for the type? In the documentation I couldn't find anything about that?
Thanks.

Symfony KnpGaufretteBundle with alias

So I have my KnpGaufretteBundle configured like this:
knp_gaufrette:
adapters:
local_shared:
local:
directory: "%shared.dir%"
create: false
filesystems:
local_shared:
adapter: local_shared
alias: defaul_fs
Then I need to inject it to my own service, I do this:
acme.user_manager:
class: %acme_user.user_manager.class%
arguments: [#doctrine.orm.entity_manager, #security.context]
calls:
- [setFilesystem, [#default_fs]]
But this breaks with exception The service definition "default_fs" does not exist.
If I use #gaufrette.local_shared_filesystem as a parameter instead of #default_fs then it works like expected. But I would like to use an alias.
Please help.
I'm assuming that you noticed that you have a typo in your config declaration:
alias: defaul_fs
has no "t"

Resources