Symfony: Speed up development enviroment for frontend developers - php

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.

Related

How to enable cache in dev mode?

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.

Symfony bundle configuration

I've just started working with Symfony and have run into a problem that I'm having a hard time tracking down information about.
I'm trying to create a bundle which has its own configuration file, e.g. configuration for doctrine connections.
All documentation I've found have never mentioned of showed how this can be set. Is it possible?
What I want to solve:
I have a bundle which when installed should handle connection to a secondary database table without any configuration needed from the main application in which the bundle has been integrated. Ultimately the configuration in the bundle should be override-able from the main application.
The bundle should be in the lack for a better work "self contained".
I've found documenation about bundle configuration. But all I've seen mentioned there is if one would like to configure the bundle and not interaction with other components (might have missed something).
tl;dr I want to have a config (e.g. AppBundle/Resources/Config/config.yml) file inside a bundle which can configure things like doctrine.
What i've tried
I've tried placing the configuration inside a config.yml file located in Resources/Config/. But I guess the file is never read.
I think it is not good idea to put something related to configuration right inside your bundle and ruin it's reusability by doing such thing. As far as I understood your task what your really need is to configure second entity manager to manage entities from secondary database when you need them. Same problem and its solution are described in following question: Doctrine 2 - Multiple databases configuration and use
Hope that will help!

Symfony 2/3 Get Classes in Directory that Implement an Interface

Is there a nice way in Symfony 2 or 3 to load all classes within a directory that implements a particular interface?
Since Symfony 3.3/3.4 it is possible by using configuration only (without a need to write custom CompilerPass):
# config/services.yaml
services:
# ...
_instanceof:
App\HandlerInterface:
tags: ['app.handler']
App\HandlerCollection:
# inject all services tagged with app.handler as first argument
arguments: [!tagged app.handler]
and if you need to restrict services to register from a single directory see importing with resource
references:
https://symfony.com/doc/current/service_container/3.3-di-changes.html#auto-configure-with-instanceof
https://symfony.com/doc/3.4/service_container/tags.html#reference-tagged-services
http://symfony.com/doc/3.4/service_container.html#importing-many-services-at-once-with-resource
Short answer is: you can't.
You don't know, what is in a file until you load it.
Long answer (taking into account what you have wrote in the comment under the question):
The only thing you know before you load a file is its name. So one of solution is to name your modules' classes (and files) with a fixed pattern like UserModule, ProductModule and so on. That way you can load all modules by their names. But this is the solution that I wouldn't suggest.
I my opinion you should change the approach and inverse the workflow. Create a class in which you will define all modules that need to be loaded. In Symfony it's called by default AppKernel, in which you define bundles (modules) to be loaded and initialized.
This has a few advantages.
You can have multiple entry points to your application and configure each one with different modules.
You may have a few different environments (like production and development) with different modules loaded in both of them. (e.g. add some modules in development like profiler)
Also dependency managment is much easier, since you can load defined modules and add their dependencies also with autoloading.
In general I think that you should avoid manual loading any php files (except autoload.php or similar that contains autoloaders) at all.

What should be first: setting or cache object

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.

Symfony Routes without app/config/routing.yaml

The tutorials I've read for Symfony 2 instructs users to enter their routing information in
app/config/routing.yml
If users want to have routing information in their own bundles, they're instructed to add a routing.yml file to their Bundle, and then point to their file from app/config/routing.yml with something like
my_route_stuff:
resource: "#CustomstuffBundle/resources/config/routing.yml"
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file? I'm looking for the ability to hand off a bundle to someone else, and have them be able to deploy it into their Symfony application without needing to edit their own app/config/routing.yml.
If this isn't possible, bonus point if anyone can explain why (i.e: the general philosophy behind) routing information is part of the AppKernel instead of the individual Bundles. I'm still a little unclear on the differences between routing.yml files and the normal Symfony config.yml files.
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file?
No, this is the way SonataAdminBundle, FOSUserBundle and a bunch of others handle it.
Why?
Routing belongs to the application, not each and every bundle. If every bundle started including their own routing files and Symfony2 autoloaded them, you would quickly have a mess of routes you may or may not want to enable in your application.
What if SonataAdminBundle wanted you to use /admin, but you already had a route there and wanted Sonata to use /sonata/admin instead? You'd need a file to override those routes and then you're back to square one!
Additionally, although caching mitigates this part, looking up files is expensive and would significantly slow down the development environment. This is why translation files are read from cache even in dev mode and you must clear the cache when you add a new translation resource. See: http://symfony.com/doc/current/book/translation.html#message-catalogues
Finally, leaving the routing out of config.yml is simply a matter of organization. Routing and configuration are two different things and don't belong in the same file.
The general idea is that every file is a thing and should only do that thing.

Categories