Symfony 3 web front controller with env - php

Symfony 3 uses two web front controllers app.php and app_dev.php. How could I change it to use one controller with usage of env variables to set the env (prod, dev) and debug.
I've tried to remove the app_dev.php but symfony tries to load that file.
Maybe this is not the way to do it, just learning symfony. Other suggestions are welcome.

The frontend controller files app.php and app_dev.php exist as examples of prod and dev respectively. As the documentation (http://symfony.com/doc/3.4/configuration/environments.html) suggests, you'll want to remove one or the other for your production deployment, or simply create a custom frontend controller for each environment, and have your apache or nginx configuration only load the appropriate file to launch Symfony.
You'll see in the file, the environment is declared and passed along with whether or not debug should be enabled.
//dev environment, with debug enabled
$kernel = new AppKernel('dev', true);
By contrast, for production:
//prod environment, debug disabled
$kernel = new AppKernel('prod', false);
If you want a single controller with some dynamic elements, I'd recommend removing app_dev.php and using app.php with custom logic before AppKernel is instantiated to do what you want.

Related

How to switch between Symfony Environments?

I got my Symfony 3.4 application deployed using PROD environment following this guide: https://symfony.com/doc/3.4/deployment.html (seems that, by default, was running on PROD, since I does not selected any environment during installation...)
In the near future, this machine will take the PRE-PRODUCTION role, so I created a new environment called pre for my application following this guide: http://symfony.com/doc/3.4/configuration/environments.html#creating-a-new-environment
Now I'm wondering how to switch this machine to new PRE environment.
I read these guides, but I'm still confused:
1) http://symfony.com/doc/3.4/configuration/environments.html#executing-an-application-in-different-environments
2) http://symfony.com/doc/3.4/setup/web_server_configuration.html
On the current machine, I'm using Apache; but for production, and following updates, I'll considere to start using NGINX. So, both options are appreciated.
If you've followed the instructions in the documentation you've entered:
Because you'll want this environment to be accessible via a browser, you should also create a front controller for it. Copy the web/app.php file to web/app_benchmark.php and edit the environment to be benchmark
then you have app_pre.php front controller with this line:
$kernel = new AppKernel('pre', false);
Just point your Apache web server to use app_pre.php instead of app.php as the front controller and your environment is switched.

Symfony4: Access DEV environment on production server

In Symfony3, when I want to browse the website in DEV environment on the "live" server, I just enter my ip address in /web/app_dev.php and open http://www.example.com/app_dev.php/ in the browser.
Since in Symfony4, the environment is now set in /.env, how can I see the DEV environment on the production machine?
EDIT: I'm looking for a solution that works in production, so applying any global changes (like e.g. setting APP_ENV=dev in /.env) is not an option.
You can change inside your .env file APP_ENV to dev like this:
APP_ENV=dev
If you set that variable symfony load the system into dev enviroment because inside Kernel.php there is this line that check that variable:
$kernel = new Kernel($_SERVER['APP_ENV'] ?? 'dev', $_SERVER['APP_DEBUG'] ?? false);
If you want to do it without change .env file you can for example set a variable in the Apache vhost or Nginx FastCgi configuration, based on the URL you are visiting from - such as APP_ENV=/home/user/app-name/dev.env or on a live server: APP_ENV=/etc/app-name.prod.env
So in this case you have many .env file but you can use rule based on url
At first this is a bad idea and that's why it wasn't possible by default to access app_dev.php on production server (symfony < 4). You're giving a lot of internal information to public and especially to attackers.
From symfony docs:
After you deploy to production, make sure that you cannot access the app_dev.php or config.php scripts (i.e. http://example.com/app_dev.php and http://example.com/config.php). If you can access these, be sure to remove the DEV section from the above configuration.
You should be able to debug most of the things from logs.
But if you really want to do it, you can just remove public/index.php and create public/app.php and public/app_dev.php like it was in symfony 3 and make it work with env variables. - https://github.com/symfony/symfony-standard/tree/3.4/web
EDIT: To be clear: you can just remove public/index.php, create public/app.php, public/app_dev.php (copies of index.php). And get inspiration from symfony 3 standard edition to adjust it to your needs.
EDIT2: As #Cerad mentioned it's a better idea to have index.php and index_dev.php file names (following Symfony4 decisions).

Laravel 5 load env file based on .env.master?

I'm planing to do something like, specifying what env file to load during application bootstrap time by creating a variable in .env.master such as ENV_VER = dev.env
This is because I have several branches such as development, release-1.1 and etc. Thus by loading the env file based on the name specified in a master env file, developers no longer have to copy and paste new variables into their local copy of .env and instead, just specify what version of env file to load in the master env file. By the way, I have several env files such as dev.env, 1.6.env etc.
Is it possible?
Definitely, me myself I tend to "bend" a framework little bit everytime and there's always a way, not always the best solution though. I'm not giving a whole implementation here, just pointing you in some direction, that might work for you.
You can extend Laravel's base application class Illuminate\Foundation\Application, which contains $environmentFile variable storing environment file loaded during appplication bootstrap or possibly override function loadEnvironmentFrom($file) or environmentFile(). The whole logic is up to you.
So basically all you need to do in order to be able to "play" with .env loading is...
Create a new application class extending Laravel's one:
namespace MyNamespace;
...
use Illuminate\Foundation\Application as App;
/**
* I'm doing alots of magic with .env in this class
*/
class Application extends App
{
...
/**
* The environment file to load during bootstrapping.
*
* #var string
*/
protected $environmentFile = '.env.main';
...
}
And now, because we have a new bootstraping class, we have to tell Laravel we want to use it. So you'll have to modify bootstrap/app.php file in point where a new instance is being created:
...
$app = new MyNamespace\Application(
realpath(__DIR__.'/../')
);
...
Note: For inspiration I recommend you to really look at Illuminate\Foundation\Application class.
In laravel 5.5+ you can, maybe earlier, you can set your server have a APP_ENV environment or server variable that the process can see (apache, command line...)
this will allow you to use a suffix or file extension on your .env files for auto loading those files...
APP_ENV=dev :: .env.dev
APP_ENV=production :: .env.production
much easier than other solutions.
If you want to look into how this is done, it starts with
1. application bootstrappers
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
2. LoadEnvironmentVariables
first the environment is determined…
\Illuminate\Foundation\Bootstrap\LoadConfiguration::bootstrap calls
\Illuminate\Foundation\Application::detectEnvironment
If
--env={env} for CLI then it will use that for APP_ENV.
Else
\Illuminate\Foundation\EnvironmentDetector::detectWebEnvironment
is called which uses a callback…
function () use ($config) {
return $config->get('app.env', 'production');
}
where app.env defaults to env('APP_ENV', 'production')
3 LoadConfiguration
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::bootstrap calls...
\Illuminate\Foundation\Application::afterLoadingEnvironment
which eventually gets to
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::checkForSpecificEnvironmentFile
which sets the environment file based on app env IF the file exists.
$this->setEnvironmentFilePath(
$app, $app->environmentFile().'.'.env('APP_ENV')
);
allowing it to load the .env.{APP_ENV} instead of .env
NOTE: Testing.
when running php unit tests. the Illuminate/Foundation will try to load the .env.testing file for configurations!

How to disable cache in symfony

I am developing a website in symfony framework. In my cache folder a huge cache is stored. I want to disable cache permanently.
While I advise against disabling the cache on a production system, you can disable the twig templating engine cache, by editing and adding to your config.yml file
twig:
cache: false
The class cache in Symfony2 can be disabled in you app.php or app_dev.php file:
$loader = require_once __DIR__.'/../app/autoload.php';
Debug::enable();
$kernel = new AppKernel('dev', true);
#$kernel->loadClassCache(); // <-- comment out this line
$request = Request::createFromGlobals();
Symfony2 - Disabling the Bootstrap File and Class Caching
I was having caching issues even when using app_dev.php. I would change a route but it wouldn't update when I tried accessing it via a browser.
I tried commenting out the anything that had cache in it (as stated above). My AppKernel('dev', true) was set to true. Nothing worked.
If I ran the console cache:clear it would fix it, but the next routing change would break again. I had to run cache:clear with every save, which was ridiculous.
My issue turned out that because I was working remotely over SFTP, PHP Storm (my editor) was "preserving timestamp" in its deployment configuration. Once I changed that configuration the issues went away. Apparently there is some caching going on that is looking at the file timestamps, even in the dev environment.
I think you can't disable "permanently cache", since Symfony applications use some cached files in order to run faster (or simply to run). Examples of this are the files that contains the dependency injection container (appProdProjectContainer.php).
You can disable some types of cache like Twig cache (as Diego Ferri said before) or Http Cache (unwrapping AppKernel with AppCache in app.php) or even Doctrine cache (in config.yml).
However I would not recommend this. The more you cache the app, the faster your app will be.
When you are working in a dev environment state, the cache is disabled anyway - I'm assuming you only want to have it disabled within development, so use the /app_dev.php file to make sure nothing is cached.
Alternatively you can empty the cache periodically on the command line using
php app/console cache:clear
You can see all the different parameters here: http://symfony.com/doc/current/cookbook/console/usage.html
This is from symfony documentation:
https://symfony.com/doc/current/bundles/override.html
If you add a template in a new location, you may need to clear your
cache (php bin/console cache:clear), even if you are in debug mode.
That means that the rules how and when the cache is cleared is not even clearly defined in the documentation.
Sometimes you want to change and debug files in vendor folder and after that even this command will not help you:
bin/console cache:clear
The only thing that will help you is to delete all content inside /var/cache/dev folder
A dirty hack for your local environment which you can use to clear cache after each request is:
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
public function terminate(Request $request, Response $response)
{
system("rm -rf ".escapeshellarg('../var/cache/dev'));
return parent::terminate($request, $response);
}
}

Symfony2: Customize database connection, cache and log folders, based on incoming request

I am trying to build a multi-tenanted solution, using an existing codebase, but with segregated databases, cache and log files.
An effective way of doing this would be to dynamically compute the following, based on an incoming requests domain name:
database connection parameters
cache folder
log folder
In Symfony1.x, I could do this by creating a custom filter class, but I don't know how to do this in Symfony2.
My question then is this:
How may I modify the above parameters for a symfon2 application - based on an incoming request?
I agree with Jurgis Gregov.
You should change in your web/app.php line:
$kernel = new AppKernel('prod', false);
to:
$kernel = new AppKernel($_SERVER['HTTP_HOST'], false);
The first argument of AppKernel is environment name
After that you can create in app/config a new config files with name:
config_name.yml
Where you can set doctrine configuration.
Your cache will be in folder: app/cache/name
And your logs will be in: app/logs/name.log (You can also set path to log in config yml file)
I don't know if there is other way to change doctrine parameters but i know that you can also chanage logs and cache folder by override methods:
getLogDir() and getCacheDir() in your app/AppKernel.php where you can use REQUEST to set it.

Categories