Symfony Validator not using cache - symfony

I have symfony 5.2.3 project with a bunch of slow validation unit tests. I want validation constraints mapping to be cached.
Following docs https://symfony.com/doc/current/reference/configuration/framework.html#reference-validation-cache I have my validator.yaml as following (I have dumped it with cli, it is actually set to this):
framework:
validation:
enabled: true
email_validation_mode: html5
cache: cache.default_redis_provider
and cache.yaml:
framework:
cache:
app: cache.adapter.filesystem
default_redis_provider: '%env(REDIS_CACHE_URL)%'
But cache is not being written in my redis. I dig in and find out that Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory is being used for this. So I put some debug there and see that it is getting $cache = null from DI. I override it manually with
$cache = new RedisAdapter(new Client('redis://redis:6379?database=1'));
and my tests are working fast and cache is written and read.
What is going on? Does this validation.cache option even work? I can put any nonsence there and it wont even throw an error

I can't see your complete configuration, but have to set the value of REDIS_CACHE_URL in '.env' file.

Related

Error: Serialization for the format json is not supported

I have integrated symfony messenger bundle and i am trying to encode that message .
It was working in Symfony 3.4.4 version . However it is giving above error in Symfony 3.4.28 version.
I have traced in symfony serialzer component , it seems that jsonEncoder is not listing in serialzer.php and which is causing this issue.
What is the reason for excluding json encoder in symfony serializer component.
See below DoctrineTransportSender:
public function send(Envelope $envelope)
{
$encodedMessage = $this->encoder->encode($envelope);
}
//messenger configuration:
messenger:
transports:
# DSN: doctrine://$repository_alias/$queue_name
# most likely we do not need more repositories (unless there's a need for splitting MySQL table with messages)
main: "doctrine://default/test"
routing:
# message type to transport routes
Bundle\QueueBundle\Message\TestMessage: [ main ]
serializer:
enabled: true
Symfony Messenger switched to PHP's native serialization/deserialization by default. Using php serialization prevents problems, e.g. accidentally omitting properties from being serialized. It will also ensure the component can be used without Symfony Serializer, which is less of an issue with Symfony 3.4, but with Symfony 4 and Flex or when using the messenger outside of Symfony you would have to install this dependency manually leading to errors.
You can still use Symfony Serializer, but it has to be configured. Considering you are on Symfony 3.4 you will likely have to do this manually by providing an appropriate Serializer-instance to the TransportFactory, see:
https://github.com/symfony/symfony/blob/4.4/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php#L1751-L1757
In Symfony 4 you can use the configuration instead, see:
https://symfony.com/doc/current/messenger.html#serializing-messages
Thanks for the response.
I have resolved above issue by adding customized serializer instead of calling messenger serializer(Which includes encoding as well decoding) and it works fine

Dynamically disable the web toolbar and profiler in Symfony 4 using .env

The web profiler is set to activate if APP_ENV is dev. It is this way on our staging server; however, a security audit is being run on our staging server and it is required that we manually turn the profiler off while keeping APP_ENV = dev.
This will successfully disable the profiler and toolbar:
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler:
{ enabled: false, only_exceptions: false }
But I want to use .env to use flags that we can control to disable each. When I try to, Symfony complains:
Environment variables "bool:SYMFONY_TOOLBAR" are never used. Please, check your container's configuration.
This leads me to an answer here, which claims:
profiler > enabled cannot be set with a runtime env variable, because that controls whether all the profiler services are created in the container (wrapping services whenever needed to be able to profile them). Changing the container entirely cannot be done at runtime (and the value of this boolean config does not end up being set itself anywhere in the container, which is why this error is triggered)
The developer says "Use a parameter in a file that is only loaded in dev mode." but I have no idea what that means; so, how can I resolve this? (.env is not a requirement, just ideal)
It is impossible to use environment flags in web_profiler.yaml due to the order in which the framework loads its environment variables. Thankfully it isn't too hard or scary to just make a new environment:
https://symfony.com/doc/4.1/configuration/environments.html#creating-a-new-environment
Create your environment, save your new web_profiler.yaml under it, then add it to bundles.php's relevant lines; in my case, my line reads like this after adding the staging environment:
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'staging' => true],

Validation Caching in Symfony >= 3.1

In a Symfony 3.1 application (which developement has been started on Symfony 2.7) I have this config item in config_prod.yml:
framework:
validation:
cache: validator.mapping.cache.doctrine.apc
To use this setup with PHP7 I needed to change this to:
framework:
validation:
cache: validator.mapping.cache.doctrine.apcu
Since Symfony 3.1 there is as well a new Cache component which for the system is configured like:
framework:
cache:
system: ???
and the official blog article states for it:
"cache.system is where Symfony components store their contents (e.g. the Serializer and Validator metadata) (...) If your server has APCu installed, the cache.system pool uses it. Otherwise, it falls back to the filesystem cache."
What I'd like to understand is whether the framework->validation->cache definition is still required or if that's part of the cache.system pool.
In later case - if I understand it correctly - framework->validation->cache could be removed and still an enabled APCu would cache validation annotations.
EDIT
If my assumption is correct then validations would be cached by the new Symfony ApcuAdapter and not by the Doctrine APC/U Cache anymore.
Based on the upgrade documentation:
"The framework.serializer.cache option and the service serializer.mapping.cache.apc have been deprecated. APCu should now be automatically used when available."
So this means indeed the old configuration can be deleted without any replacement as long as apcu is installed and enabled.

How can I get the Doctrine entity metadata before compiling Symfony container?

In one Symfony bundle I define a compiler pass to preprocess some configuration. Part of that config is based on Doctrine entities, so I need to get the full metadata information for all application entities.
The compiler pass is executed very late (PassConfig::TYPE_BEFORE_REMOVING). I'm using $container->get('doctrine') like this to get the entity metadata:
$em = $container->get('doctrine')->getManagerForClass($entityClass);
$entityMetadata = $em->getMetadataFactory()->getMetadataFor($entityClass);
However, this is causing random failures for some users because of the use of the doctrine service during the Symfony container compilation.
I'd recommend to change your entities addressing. Mainly - create your models with interfaces and make entities implementing them.
Using resolve_target_entities Doctrine will "convert" them to the particular classes.
An example code is here: https://github.com/Sylius/SyliusResourceBundle/blob/master/DependencyInjection/Compiler/DoctrineTargetEntitiesResolverPass.php
Just make sure your bundle is registered before DoctrineBundle is registered.
Then - in your whole app - instead of AppBundle::Entity addressing, use FQDN of interface bound to an entity earlier.
I've experimented a bit with compilers and services and it's a very bad idea to base on cross-bundle services under compiling container process... Why? It's not reliable - sometimes it will work as you want, sometimes it will fail as you described.
Thank you all for your comments and ideas. I post an answer to explain how I solved this problem.
Trying to use the Doctrine service in a compiler pass was creating more and more problems for our users (and it was creating other minor issues with other services such as Twig). So this was definitely a bad solution for our needs.
So at the end I decided to change everything. We no longer use a compiler pass to process the configuration and instead we use a regular PHP class called during runtime.
In the dev environment, the configuration is processed for each request. It's a bit slower than before, but we prevent any caching issue. In the prod environment we use Doctrine Cache to process the configuration once. Besides, we've create a cache warmer to create the cached configuration before the first request hits the application.

asp.net mvc BundleConfig - is localhost

BundleTable.EnableOptimizations = false;
Hi! I want to set bundle optimization to false if I app is started on localhost. Since it is called from app-start method I cant get to the Request object. Other posibility is Transformation config's but they are not used on this project.
Does anybody has some other solutions?
In my opinion you better use the configuration manager. When in 'Debug' mode disable the optimizations, when building in 'Release' mode enable it.
It's also possible to create your own configurations, for instance 'localhost' build.
This is the setting you need to change for the different build configurations:
<Optimize>true</Optimize>
or
<Optimize>false</Optimize>
This will keep your code cleaner as you don't have to write any exceptions.
This worked for me
if (!HostingEnvironment.IsDevelopmentEnvironment)
BundleTable.EnableOptimizations = true;

Resources