How clear routing cache in Symfony 2 - symfony

I override routing loader (routing.loader) for set requirements key {_locale} in all my paths and set defaults this key. All locales saved in database. And i want clear routing cache (Matcher and Dumper cache class) after save new locale in database, because requirements parameter load from DB.
Thank.

Symfony cached route files:
appDevUrlMatcher.php
appDevUrlGenerator.php
in your cache dir, var/cache/dev(prod)
just delete these files
protected function warmUpRouteCache() {
$router = $this->get('router');
$filesystem = $this->get('filesystem');
$kernel = $this->get('kernel');
$cacheDir = $kernel->getCacheDir();
foreach (array('matcher_cache_class', 'generator_cache_class') as $option) {
$className = $router->getOption($option);
$cacheFile = $cacheDir . DIRECTORY_SEPARATOR . $className . '.php';
$filesystem->remove($cacheFile);
}
$router->warmUp($cacheDir);
}
it works for me.

php app/console cache:clear
php app/console cache:clear --help
Additional cache warm up tasks are executed after clearing the cache in order to have regenerated caches available during runtime - see detailed help for further information.
https://symfony.com/doc/3.4/console/usage.html
https://symfony.com/doc/4.0/console/usage.html

Related

Symfony need cache:clear too often

I started learn Symfony 3 days ago and have the problem with cache or something else.
The first I have RegisterController:
public function index(Request $request, UserPasswordEncoderInterface $encoder)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()){
$user = $form->getData();
$user->setPassword($encoder->encodePassword($user, $user->getPassword()));
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
}
return $this->render('register/index.html.twig', [
'form' => $form->createView(),
]);
}
Its working fine. But when I write before
$user = new User();
this line $this->denyAccessUnlessGranted("ROLE_ADMIN"); - I have access "Access Denied" its okay because I have another role.
But when I delete this line code $this->denyAccessUnlessGranted("ROLE_ADMIN"); and refresh the page I have screen:
This page isn’t working
symfony.local didn’t send any data.
ERR_EMPTY_RESPONSE
and I can't access this page anymore. I have to clear the cache:
php bin/console cache:clear
or restart apache.
Can you tell me what is going on and how to fix it?
I have problem with PHP version: 7.4.0 and php fpm . I do update the php to 7.4.3 and now is okay. Thanks for your helps.
Symfony can be configured for different environments and those environments can change how Symfony behaves. If you a running a production environment, Symfony will perform a lot of caching to increase the speed which it serves pages to your guests. If you are in DEV mode it will reload most code changes each time you run it.
However web servers / php can also cache your files as well. If you are in DEV mode in Symfony, and still having this problem check the caching settings in the php.ini file.

Symfony doesn't remove cache by tags

Symfony version: 3.4.9
Reproducing:
$cache = new TagAwareAdapter($this->get('cache.app'));
$pagination = $cache->getItem(PostTypeDictionary::CACHE_MEDIA_PREFIX . $postType . $request->get('page', 1));
if (!$pagination->isHit()) {
$data = getSomeData();
$pagination->tag(
[
PostTypeDictionary::CACHE_MEDIA_PREFIX,
PostTypeDictionary::CACHE_MEDIA_PREFIX . $postType,
]
);
$pagination->set($data);
$cache->save($pagination);
} else {
$data = $pagination->get();
}
In redis i see two keys:
1) "zG3lSHyaSM:\x00tags\x00cache.media.01"
2) "zG3lSHyaSM:cache.media.01"
First contains: "a:2:{s:12:\"cache.media.\";i:0;s:13:\"cache.media.0\";i:0;}"
Second contains data
Then i call cache clearing by tags:
(new TagAwareAdapter($this->get('cache.app')))->invalidateTags([PostTypeDictionary::CACHE_MEDIA_PREFIX]);
Redis store one more key "zG3lSHyaSM:cache.media.\x00tags\x00", which contains: "i:1;"
And that's all, old cache available.
Another cache adapters have the same problem.
What i'm doing wrong?
I found that Symfony's cache component has a bug in a most recent version (3.4.9). I think it's related to https://github.com/symfony/cache/commit/51a9eef3091b2c06f63d8b1b98de9d101b5e0e77 . Simply downgrading to 3.4.8 solved this issue for me.

Symfony2: How do I clear all of Symfony's (and all 3rd party plugins) cache in 1 command?

so I've been testing Doctrine queries and other Symfony code and I have to run several commands just to clear Doctrine/Symfony caches. I was searching for the net and came across another command to clear Assetic assets/etc.
From what I've read
php app/console cache:clear
will only clear Symfony cache. it won't include Doctrine and perhaps more.
I know I can create a bash script to clear all my caches but this obviously means I know all the "clear cache" commands. I only found out about the Assetic clear cache/assets by accident. What about those I don't know?
So is there 1 "clear cache" command that can do it for me? This will have to include Symfony/Doctrine/Assetic/Twig and whatever plugins I have installed.
Thanks a lot
What you are looking for is highly dependent on the developer of the bundle that uses the cache. Not even doctrine, that comes with the standard version of symfony has its cache clear command integrated. But what you can do is extend the default symfony command with a listener that runs all the cache clear command you want like this:
<?php
namespace DefaultBundle\Event\Listener;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Process\Process;
class CacheClearListener implements CacheClearerInterface
{
private $environment;
/**
* #return array
*/
private static function getCommands()
{
return array(
'php ./app/console doctrine:cache:clear-metadata --no-debug --flush',
'php ./app/console doctrine:cache:clear-query --no-debug --flush',
'php ./app/console doctrine:cache:clear-result --no-debug --flush'
);
}
public function clear($cacheDir)
{
$output = new ConsoleOutput();
$output->writeln('');
$output->writeln('<info>Clearing Doctrine cache</info>');
foreach (self::getCommands() as $command) {
$command .= ' --env='.$this->environment;
$success = $this->executeCommand($command, $output);
if (!$success) {
$output->writeln(sprintf('<info>An error occurs when running: %s!</info>', $command));
exit(1);
}
}
}
/**
* #param string $command
* #param ConsoleOutput $output
*
* #return bool
*/
private function executeCommand($command, ConsoleOutput $output)
{
$p = new Process($command);
$p->setTimeout(null);
$p->run(
function ($type, $data) use ($output) {
$output->write($data, false, OutputInterface::OUTPUT_RAW);
}
);
if (!$p->isSuccessful()) {
return false;
}
$output->writeln('');
return true;
}
/**
* #param Kernel $kernel
*/
public function setKernel(Kernel $kernel)
{
$this->environment = $kernel->getEnvironment();
}
}
Register the listener like this:
<service id="cache_clear_listener" class="DefaultBundle\Event\Listener\CacheClearListener">
<call method="setKernel">
<argument type="service" id="kernel"/>
</call>
<tag name="kernel.cache_clearer" priority="254" />
</service>
And that is all. Now all you need to do is keep adding your new cache clear command to the getCommands() method. In order to find this commands you can run something like
php app/console | grep cache
to see all available commands that contain the word "cache" in them
After your listener is set, every time you run php app/console cache:clear it will trigger all the command that you listed in the getCommands() method of your listener.
Hope this helps,
Alexandru

Symfony app/console cache:clear --env=prod and cache (APC, Memcached, etc)?

I'm using a Memcached server (along with memcache PHP extension) to cache validator metadata and Doctrine metatada/result/query cache driver.
Everything works as expected and is fast compared to filesystem cache.
My question is, does the command:
php app/console cache:clear --env=prod --no-debug
automatically clear all types of cache (including memcache)?
After running this command and checking the server stats, items count is always the same as well as cache occupation:
My configuration, where %prod_cache% parameter is actually the string memcache:
# Framework Configuration
framework:
validation:
cache: %prod_cache% # Matches validator cache service
# Doctrine Configuration
doctrine:
orm:
metadata_cache_driver:
type: service
id: cache_%prod_cache%
result_cache_driver:
type: service
id: cache_%prod_cache%
query_cache_driver:
type: service
id: cache_%prod_cache%
# DoctrineCacheBundle Configuration
doctrine_cache:
providers:
memcache:
type: memcache
alias: cache_memcache
# Services
services:
validator.mapping.cache.memcache: # Validator cache service
class: Symfony\Component\Validator\Mapping\Cache\DoctrineCache
arguments: [#cache_memcache]
cache:clear
The cache:clear command doesn't clear the Doctrine caches. It only clears some Symfony 2 framework specific caches, mainly the app/cache (or var/cache) directories.
Doctrine commands
In order to clear the Doctrine caches, use:
doctrine:cache:clear-metadata --env=prod
doctrine:cache:clear-query --env=prod
doctrine:cache:clear-result --env=prod
Additional caches
If you use additional cache stores, you'll have to clear them yourself. You can look at the doctrine:cache:clear-* commands to get inspired on how to create your own command.
But looking at you configuration, you use a single cache store for the 3 Doctrine caches and Symfony Validator cache. So calling just one of the doctrine:cache:clear-* should clear everything.
Off topic
When using a cache system like APC, OPcache, and maybe others, you'll have to understand that when you run a PHP script from the command line, a different memory space is used then when running a PHP script from a webserver.
In other words: when you clear such caches from the command line, the caches used by the webserver are not affected. In order to clear the webserver caches, you'll need to run the cache clear script(s) from the webserver itself.
This is not an issue for memcached, because it's a separate program managing its own memory space.
You have to clear external cache yourself, from the doc (SF 2.5):
There may be lots of other things that you need to do, depending on
your setup:
[...] Clearing your APC cache
See: http://symfony.com/doc/current/cookbook/deployment/tools.html#e-other-things
This command do not clears the Memcache since it is a standalone distributed memory cacher.
It clears the Symfony cache only.
To clear the memcache you have to run manually :
echo 'flush_all' | nc localhost 11211
But I think you know that already.
The clear:cache commands only empty the symfony cache in the filesystem then warmup it.
You can use some additional bundles to clear other caches:
Memcache: https://github.com/LeaseWeb/LswMemcacheBundle
APC: https://github.com/ornicar/ApcBundle
If you check vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php you will see that Symfony clears the cache using the file system service. It clears the cache by removing the old directory.
Here is the exact function (Symfony 2.4)
protected function execute(InputInterface $input, OutputInterface $output)
{
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
$oldCacheDir = $realCacheDir.'_old';
$filesystem = $this->getContainer()->get('filesystem');
if (!is_writable($realCacheDir)) {
throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
}
if ($filesystem->exists($oldCacheDir)) {
$filesystem->remove($oldCacheDir);
}
$kernel = $this->getContainer()->get('kernel');
$output->writeln(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
$this->getContainer()->get('cache_clearer')->clear($realCacheDir);
if ($input->getOption('no-warmup')) {
$filesystem->rename($realCacheDir, $oldCacheDir);
} else {
// the warmup cache dir name must have the same length than the real one
// to avoid the many problems in serialized resources files
$warmupDir = substr($realCacheDir, 0, -1).'_';
if ($filesystem->exists($warmupDir)) {
$filesystem->remove($warmupDir);
}
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
$filesystem->rename($realCacheDir, $oldCacheDir);
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
sleep(1); // workaround for Windows PHP rename bug
}
$filesystem->rename($warmupDir, $realCacheDir);
}
$filesystem->remove($oldCacheDir);
}
If you use a cache like APC that uses different memory space for console and web server, you have no other why then to have and interface where you manually clear the cache.
For memcache, memcached, etc. you can hook into the cache:clear command by creating a listener over the kernel.cache_clearer event that runs both the doctrine cache clear commands.
Whatever method you use for clearing the cache, some cache types like memcache, will not release the memory used. Instead they will unset the key the next time a get command is issued on that key, or when the memory is full and some keys need to be evicted.
class CacheClearDoctrineListener implements CacheClearerInterface
{
/**
* #var ContainerInterface
*/
protected $container;
protected $environment;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
$this->environment = $container->get('kernel')->getEnvironment();
}
public function clear($cacheDir)
{
$this->clearCacheMetadata();
$this->clearCacheQuery();
}
protected function clearCacheMetadata()
{
// clear cache metadata
$application = new Application($this->container->get('kernel'));
$application->setAutoExit(false);
$output = new ConsoleOutput();
$arguments = array(
"command" => "doctrine:cache:clear-metadata",
"--env" => $this->environment
);
$input = new ArrayInput($arguments);
$returnCode = $application->run($input, $output);
if ($returnCode != 0) {
$output->writeln(json_decode(rtrim($output)));
}
}
protected function clearCacheQuery()
{
// clear cache query
$application = new Application($this->container->get('kernel'));
$application->setAutoExit(false);
$output = new ConsoleOutput();
$arguments = array(
"command" => "doctrine:cache:clear-query",
"--env" => $this->environment
);
$input = new ArrayInput($arguments);
$returnCode = $application->run($input, $output);
if ($returnCode != 0) {
$output->writeln(json_decode(rtrim($output)));
}
}
}
Declare your service something like this:
<service id="cache_clear_doctrine_clearer" class="%namespace_of_your_listener%">
<call method="setContainer">
<argument type="service" id="service_container"/>
</call>
<tag name="kernel.cache_clearer" priority="254" />
</service>
try this:
php app/console memcached:clear --clearAll default

Symfony2 cache:clear outputs the content of services.yml file

In Symfony2, everytime I clear my cache via the console:
php app/console cache:clear
The console prints out the contents of my services.yml file! If I manually delete the cache via rm -rf app/cache/* (which I have to do since my console user doesn't have access to the apache user www-data, for some reason, despite being in the same group because the files are created as 640 instead of 660), then the public website also prints it out the FIRST time the page is loaded and the cache is generated.
NOTE: this prints out even if services.yml is NOT loaded in the app/config/config.yml (just by existing, somehow it's being referenced)
We import the services.yml file:
# /app/config/config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: "#AcmeBundle/Resources/config/services.yml" }
Then set global services in the services.yml file:
# /src/Acme/Bundle/Resources/config/services.yml
# TODO: ALERT! this prints out whenever I clear the cache...
services:
#This is a service so that we can access the view object anywhere
acme.view:
class: Acme\Bundle\Controller\ViewController
arguments: [ #doctrine.orm.entity_manager ]
Question: Any ideas why this file is printing out every time I clear the cache?
This was caused by changing the /Acme/Bundle/Resources/config/services.yml services parameters from PHP to YAML format (I created as PHP originally in my testing).
The reference to the service parameters file is hard coded in the /Acme/Bundle/DependencyInjection/AcmeBundleExtension.php in two places.
Here is the broken code:
class AcmeBundleExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
Since the services.yml was being loaded as a PHP file, it was just printing out text whenever the cache was recreated. Amazingly, all the services still actually loaded somehow...!
So take note, if you change the config file from PHP to YAML (or vice versa) you have to update:
$loader->load('services.yml');
(which I did)
But also you must update the loader function from Loader\PhpFileLoader to Loader\YamlFileLoader:
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
Of course that seems obvious, but if you are new to Symfony, take note that converting formats of your service config file requires more than just changing your file name.

Resources