I'm working on a heavy-load Symfony optimization, trying out template cache, doctrine cache, etc. But unless I'm wrong, those caches are disabled in dev, so it's hard to evaluate the effect of those optimizations.
Is there a way to enable caching in dev mode, so I can the application optimization results while keeping the debug bar?
Note that there are couple of assumptions in your question that are not true:
By default, Twig is always cached. Check the docs here. You can only disable caching, if for some reason you need to disable it during development. But more likely than not, it's not going to be great for you.
There is no default Doctrine caching enabled on production. If you want to enable caching, you'd need to do it yourself (by creating the appropriate file in config/packages/prod/doctrine.yml, but you'd first need to verify exactly what type of caching you'd need and how to configure it. Check some docs about doctrine caching here.
In the end, changing settings on dev (or any environment) it's just a matter of creating the another file with the appropriate settings within config/packages/[environment_name].
You should already have a few inside config/packages/dev/.
To create specific settings for an environment just add a couple of files to adjust these settings.
E.g. you could have a config/packages/dev/doctrine.yml with this inside (a basic doctrine caching configuration):
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '#doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '#doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
Have you checked the configuration for each of these parts? For example, in older Symfony versions, there could be a file somewhere (depending on the Symfony version you've started the project with, it could for example reside at config/packages/dev/twig.yaml) that defines the Twig cache as following:
twig:
cache: false
By setting this to a valid caching directory, you can enable the cache, regardless of the environment running your application.
In other packages, there might be similar settings. Have a look for overriden settings, either in config/packages/dev and config/packages/prod for more recent versions or files like config/services_prod.yaml and config/services_dev.yaml for a bit older versions. But without knowing which packages you use, it's hard to provide a general answer.
Related
I have a Symfony application, and I would like to use Redis as a caching system. The default caching system for Symfony out of the box is filesystem caching.
from the documentation I learned there are two named caches in Symfony; cache.app and cache.system so I set both to Redis with the following cache.yaml:
framework:
cache:
# Put the unique name of your app here: the prefix seed
# is used to compute stable namespaces for cache keys.
prefix_seed: myteam/myapp
default_redis_provider: "redis://redis:6379"
# The app cache caches to the filesystem by default.
# Other options include:
# cache.app via Redis
app: cache.adapter.redis
# cache.system also
system: cache.adapter.redis
After doing this, I loaded an example page and monitored the cache folder. I found that files were still being created in the cache folder, even though keys were being created in Redis.
I know that Symfony do not recommend messing with the files that the Kernel creates in the file cache, but even the cache/prod/Containerxxxxx folder was being written to.
What could be caching in the folder that isn't part of app or system? Is there another named cache that I have missed?
The files at cache/prod/Containerxxxxx are the compiled container files.
These are always written into your file system and never be written into other, secondary cache systems.
Symfony wouldn't know how to access Redis in the first place without getting that information from the container, the container is always cached to the filesystem when compiled and built.
cache.system is used for things like annotations, serializer, and validation; but not for the compiled container itself.
cache.app is the application cache, that is available for you to use in your app if you typehint CacheInterface or Psr\\Cache\\CacheItemPoolInterface in your services methods.
Summing up, there is no other cache you can configure so Symfony would store the compiled container there. These files are code and are stored on the filesystem.
I have been using Symfony since the start of the 3.x era, and am looking to create new sites on 4.x. It seems OK at first glance (just looking at the demo site), however, I'm not liking the idea of webpack encore.
When I installed the demo, it has issues as links are screwed up due to the sub-folder the project is in. I found out this is because I need to update settings in webpack encore, however, I can not deploy the changes as I do not have node.js installed, I run apache.
Most cpannel hosting currently does not support node.js, so it seems silly to have a reliance on node.js! I know I can do the deploy on a local server and then just send the deployed version up to the online server, but that can just be asking for problems, I want to do all development in an environment similar to the production environment.
Because of this I am looking at options in Symfony 4 to do asset management that will not need another server environment like node.js (or even yarn). I used assetic in the past, but support for it in Symfony 4 has been dropped. I want something that is easy to set up and use.
You can still go with assetic if you're not confortable with the node.js thing (which is understandable).
From symfony's doc :
Assetic is a pure PHP library that helps to process & optimize your
assets (similar to Encore). Even though we recommend using Encore,
Assetic still works great
Ref link : https://symfony.com/doc/current/frontend.html
Drawback being that you can't be sure whether or not it will still work with SF's next majors updates, I agree, but odds are new solutions will appear in the future, since you're not the only one complaning about it.
To follow up with your comments, with the use of the assets section of the configuration to make him fetch files wherever you want, I was thinking about something like (with proper rights given to folders) :
assetic:
/* ... */
read_from: %kernel.root_dir%/../build
write_to: %kernel.root_dir%/../build
/* ... */
assets:
common:
inputs:
- %kernel.root_dir%/../assets/js/your_file1.js
- %kernel.root_dir%/../assets/js/your_file2.js
isolatedFileExample:
inputs:
- %kernel.root_dir%/../assets/js/your_file3.js
Didn't test it though, keep us updated about your tests. Might be of some interest.
I'm trying to create a development enviroment for the frontend developers. As long as they don't change any php code I thought it might be a good idea do this, if possible:
Create a new entry point all app_frontend.php i.e., disabling the debug
Create a config_frontend.yml file and cache php files generation but disable twig cache as well as js and css
Is there any way to do this? I'm not sure if it's possible
You can create as many environments as you want. After all, environments are just sets of different configuration, nothing more.
This means that if you want to create a frontend environment, you have to do just some things:
Create some sort of front controller that constructs AppKernel using new AppKernel('frontend', false);
As AppKernel::registerContainerConfiguration() in the Symfony Standard Edition uses the environment to determine the config file to load, you have to create app/config/config_frontend.yml as well (or change the logic in the AppKernel method)
Inside this config file, make sure you import the settings that are in common. This often means importing app/config/config.yml. Besides that, you can configure things how you like it. E.g.
# app/config/config_frontend.yml
imports:
- { resource: config.yml }
twig:
cache: false
You can read more about this topic in the Symfony docs.
I've a very basic question which drives me nuts. I maintain my own little framework. I can configure the framework with a YAML/JSON/XML/whatever settings file. The framework uses also a cache (any of memcached/couchbase/whatever even file based caching if no caching server is installed).
So no I've the following problem: I like to cache my settings parsed from the settings file in the cache but I would like to define the cache type used for that in the settings file.
What would be a proper solution for this? I can't imagine how I should manage this which leeds me to the thought that I probably have a very basic design / architecture error in my framework. Is there any solution at all?
Well as my experience from Symfony1 and Symfony2 goes, cache as much as you can.
In their production environment everything is cached, so you would run into your problem that the cache type is described in the settings file which is itself cached.
The proper solution to this is: As in Symfony: Delete the cache in prod, once you made changes to settings.
For dev the settings are always re-read as you do not profile in debug, so ease of development is more important that bootstrap time.
I recommend splitting this like symfony did.
For prod your settings are seldomly changed so parsing a file that can be cached is wasted resources and speed is typically priority 1 in prod.
Edit: Your options regarding the order of bootstrapping:
Always read settings first then decide which cache you will need.
Use a settings configuration cache that is hard coded (e.g file based)
I recommend using option 2. Your framework is cache agnostic as this can be configured, which is good but for basic settings of your framework you simply do not need that. You don't want to setup different cache mechanisms like memcache, sql etc just for basic settings.
Symfony solves this by the most effective way, as it provides a default cache generation for settings and this is simply a php file. Thats all. When symfony loads settings it looks for a certain file to include, if it does not exist, symfony caches it by creating plain php and then reads it.
You can determine the file type from the file extension. Then you can read the cache type and create a cache. The cache should be a singleton.
For the creation of the cache I would use an abstract factory, which implementation is dependent on the file type. The appropriate implementation of the abstract factory then can read the settings file and create the right cache.
The new app I'm working on is using Symfony2. There is no database connection to use. Instead it's build upon many web service calls. Under Symfony/app/config, I would like to remove all database_* entries but when I do that, I get a
ParameterNotFoundException: You have requested a non-existent parameter "database_driver"
The error is obvious. But how do I decouple and remove the database configs from the app itself?
Remove DoctrineBundle initialisation from your AppKernel and doctrine configuration from your app/config/config*.yml files. It registers doctrine configuration in the container. That's why container complains if you try removing the parameters (bundle is enabled and looks for those parameters).
In latest versions of Symfony you'll also need to remove the doctrine channel from monolog configuration in config_dev.yml (remove the channels: ["doctrine"] line).
Symfony2 is integrated with Doctrine2 by default. You cannnot remove the configuration, unless you set another integration bundle.
It would be effortless if you simply leave these fields empty. A connection to the database would be made only when the application requires it, which, in your case, should not happen.