If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
We missed a deploy step! We're not clearing Symfony's cache. That sounds like
a job for a new task! Call it "Clear Cache". It's easy: we just need to run a command:
{{ symfony_console_path }} cache:clear --env=prod
:
- hosts: vb | |
... lines 3 - 10 | |
tasks: | |
... lines 12 - 188 | |
- name: Clear cache | |
command: '{{ symfony_console_path }} cache:clear --env=prod' | |
... lines 191 - 206 |
Easy! Except... that --env=prod
part is interesting. Sometimes I might want
to deploy our app in the prod
environment - like if we're deploying to production.
But other times, like if we're deploying to some test machine, I might want to deploy
our app in the dev
environment.
What I'm saying is: I want that environment to be configurable. And actually, this is important in two places: here, and when installing the Composer dependencies.
Google for "Symfony deploy" to find a page on Symfony.com. Scroll down to a section about installing and updating your vendors. Ah, so it recommends that when you deploy, you use:
composer install --no-dev
That's actually what the composer
module tried to do by default. But then we -
via a no_dev
option - told it to stop that nonsense!
- hosts: vb | |
... lines 3 - 10 | |
tasks: | |
... lines 12 - 149 | |
- name: Install Composer's dependencies | |
composer: | |
... line 152 | |
no_dev: no | |
... lines 154 - 206 |
We had to do that because some of the Composer post-install commands in a Symfony
app require the packages in the require-dev
section.
In reality, this --no-dev
flag is not a big deal. But, we can use it... as long
as we set an environment variable: SYMFONY_ENV=prod
. Yep, those problematic post-install
commands are setup to look for this environment variable, and not to do certain
things rely on the require-dev
dependencies.
So this is our mission: make the environment configurable, use it in the "Clear Cache" task and set a new environment variable.
How? Start at the top: add a new vars_prompt
key with name
set to symfony_env
:
- hosts: vb | |
... lines 3 - 10 | |
vars_prompt: | |
- name: symfony_env | |
... lines 13 - 221 |
Then, prompt: Enter the environment for your Symfony app (prod|dev|test)
:
- hosts: vb | |
... lines 3 - 10 | |
vars_prompt: | |
- name: symfony_env | |
prompt: "Enter the environment for your Symfony app (prod|dev|test)" | |
... lines 14 - 221 |
As you're probably guessing, Ansible will now ask us what environment we want to use.
Set a default value to prod
and private: no
- you can set that to yes to obscure
passwords as you type them:
- hosts: vb | |
... lines 3 - 10 | |
vars_prompt: | |
- name: symfony_env | |
prompt: "Enter the environment for your Symfony app (prod|dev|test)" | |
default: prod | |
private: no | |
... lines 16 - 221 |
Cool!
Next question: how can we use this variable to set an environment variable? How about...
an environment
key! Yep, setting environment variables is a native task for
Ansible. Set SYMFONY_ENV
to {{ symfony_env|lower }}
:
- hosts: vb | |
... lines 3 - 10 | |
vars_prompt: | |
- name: symfony_env | |
... lines 13 - 16 | |
environment: | |
SYMFONY_ENV: "{{ symfony_env|lower }}" | |
... lines 19 - 221 |
This uses the variable we just set... but pipes it through a lower
filter...
just in case we get crazy and use upper-case letters.
To see what this all looks like, at the top, let's debug some variables. First,
debug one called ansible_env
:
- hosts: vb | |
... lines 3 - 19 | |
tasks: | |
- debug: | |
var: ansible_env | |
... lines 23 - 221 |
This is a built-in variable that has a lot of info about the "host" environment - meaning, the machine (or machines) that you're running Ansible against. It should also contain our environment variable.
Let's also debug the symfony_env
variable that we set above:
- hosts: vb | |
... lines 3 - 19 | |
tasks: | |
- debug: | |
var: ansible_env | |
- debug: | |
var: symfony_env | |
... lines 26 - 221 |
Oh, and down on the "Clear Cache" task, I forgot to add the tag for deploy
:
- hosts: vb | |
... lines 3 - 19 | |
tasks: | |
... lines 21 - 203 | |
- name: Clear cache | |
command: '{{ symfony_console_path }} cache:clear --env=prod' | |
tags: | |
- deploy | |
... lines 208 - 221 |
Change over to your terminal and run the playbook - but take off the -t
option
so that everything runs:
ansible-playbook ansible/playbook.yml -i ansible/hosts.ini
Yes! Right at the start, it asks us for the environment. I'll leave it blank
to use prod
. Then, hit ctrl+c to quit: we can already see the variables!
First, it printed ansible_env
... which has some pretty cool stuff! It has a HOME
key for the home directory, PWD
for the current directory and other goodies. AND,
it has SYMFONY_ENV
set to prod
. Not surprisingly, the symfony_env
variable
also prints prod
.
Try this again.. but be tricky... with an uppercase PROD
:
ansible-playbook ansible/playbook.yml -i ansible/hosts.ini
Yep! The environment variable was lowercased, but not the symfony_env
variable.
That's no surprise... but if we want to guard against this, it will be a problem
in a minute when we try to use this in more places... like down on my "Clear Cache"
task:
- hosts: vb | |
... lines 3 - 19 | |
tasks: | |
... lines 21 - 203 | |
- name: Clear cache | |
command: '{{ symfony_console_path }} cache:clear --env=prod' | |
... lines 206 - 221 |
We could keep using the lower
filter. But, there's a cooler way: a "pre task".
Hey Juan,
Hm, at the first sight, it's correct. Let's debug a bit more. Could you SSH to your server and run "composer install" manually? Do you have the same error? Also, you could try to always install dev deps with simply "no_dev: no". Does it fix the problem? Btw, could you try it manually locally? Are you sure you don't have the same problem and fixtures could be loaded successfully locally?
Cheers!
HeyVictor
En aws server with ssh:
When I try composer install (dev) is all ok.
[OK] All assets were successfully installed.
But when I try: composer install --no-dev
//- other bundles ok
- Installing willdurand/hateoas-bundle (1.3.0): Loading from cache
Generating autoload files
> Incenteev\ParameterHandler\ScriptHandler::buildParameters
Updating the "app/config/parameters.yml" file
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineFixturesBundle" from namespace "Doctrine\Bundle\FixturesBundle".
Did you forget a "use" statement for another namespace? in /var/www/project/app/AppKernel.php:30
Stack trace:
#0 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(450): AppKernel->registerBundles()
#1 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(116): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /var/www/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(137): Symfony\Component\HttpKernel\Kernel->boot()
#3 /var/www/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(124): Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands()
#4 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(90): Symfony\Bundle\FrameworkBundle\Console\Applica in /var/www/project/app/AppKernel.php on line 30
Script Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache handling the symfony-scripts event terminated with an exception
[RuntimeException]
An error occurred when executing the "'cache:clear --no-warmup'" command:
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineFixturesBundle" from namespace "Doctrine\Bundle\FixturesBundle".
Did you forget a "use" statement for another namespace? in /var/www/project/app/AppKernel.php:30
Stack trace:
#0 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(450): AppKernel->registerBundles()
#1 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(116): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /var/www/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(137): Symfony\Component\HttpKernel\Kernel->boot()
#3 /var/www/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(124): Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands()
#4 /var/www/project/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(90): Symfony\Bundle\FrameworkBundle\Console\Applica in /var/www/project/app/AppKernel.php on line 30
install [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--no-suggest] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--ignore-platform-reqs] [--] [<packages>]...
Thanks!
More info:
In my LoadUser.php
When I installed composer with --no-dev the namespaces next are wrong, because not exits Doctrine\Common\DataFixtures.
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
Yes, this sounds correct if you register DoctrineFixturesBundle in AppKernel only for dev/test environments.
Cheers!
victor First I want to thank you for all your help, I have solved the error
The installation and configuration were right, but in DoctrineFixtures classes I was using a OrderedFixtureInterface old, at the current version is different....
//https://symfony.com/doc/master/bundles/DoctrineFixturesBundle/index.html
public function getDependencies()
{
return array(
UserFixtures::class,
);
}
I'm really grateful to you
I will edit the first comment to report that the error is to another different problem than this lesson . Or if you wish, I can delete it so as not to confuse.
Thanks!
Hey Juan,
Don't worry too much about your previous comments, we'll keep them ;)
Hm, it's a bit weird that fixtures broke your prod environment even when you do not use fixtures in prod at all. But I really glad you got it working!
Cheers!
Hey Juan,
Hm, are you sure you include DoctrineFixturesBundle namespace in AppKernel for dev/test environment only? And what about your local machine? Does it work locally when you execute "composer install --no-dev"?
UPD: I can suggest you to try to upgrade Composer dependencies with "composer update". It will pull latest versions and regenerate composer.lock. Then, try to execute "composer install --no-dev" again.
Cheers!
Also, let's see SYMFONY_ENV works well, try to follow a few steps:
- SSH to AWS server
- cd /to/project/dir
- try again to install deps without importing SYMFONY_ENV, just execute: "composer install --no-dev"
- On this step you should see the error you reported, right?
- Now let's export prod environment var by executing: "export SYMFONY_ENV=prod"
- And in the same terminal tab you exported SYMFONY_ENV, execute again: "composer install --no-dev"
Do you still have that error? Or, does it work now?
Cheers!
HI victor ,
In local:
#~/.zshrc
export SYMFONY_ENV="prod"
When I run in my terminal$ echo $SYMFONY_ENV return prod
- composer install --no-dev [local] ..... BUUM!!!!
...
PHP Fatal error: Uncaught ReflectionException: Class Doctrine\Common\DataFixtures\AbstractFixture not found in /Users/juanluisgarciaborrego/Sites/project/src/AppBundle/DataFixtures/ORM/LoadUserData.php:10
...
Fatal error: Uncaught ReflectionException: Class Doctrine\Common\DataFixtures\AbstractFixture not found in /Users/juanluisgarciaborrego/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php on line 179
...
[RuntimeException]
An error occurred when executing the "'cache:clear --no-warmup'" command:
Fatal error: Uncaught ReflectionException: Class Doctrine\Common\DataFixtures\AbstractFixture not found in /Users/juanluisgarciaborrego/Sites/project vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php on line 179
Symfony\Component\Config\Exception\FileLoaderLoadException: Class Doctrine\Common\DataFixtures\AbstractFixture not found in /Users/juanluisgarciaborrego/Sites/project/app/config/services.yml (which is being imported from "/Users/juanluisg
arciaborrego/Sites/project/app/config/config.yml"). in /Users/juanluisgarciaborrego/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php on line 179
=(
Thanks!!!
Victor,
I'm trying and I think
It's all ok.
First I run ansible-playbook -i ......... with environment DEV, so it installs :
- create BD
- schema update
- fixtures load
That is good, the next, I run with environment PROD, I ansible is happy and skypped Load data fixtures and Warmup cache.
But, this I think not is the workflow correct.
Hey Juan,
I agree, that sounds not quite right workflow. In prod environment you really need to skip loading fixtures, but you still need to clear/warm up the cache, but this time with "--env=prod" option. Also, for production you won't just update schema with bin/console doctrine:schema:update, you need to run migrations instead to prevent loosing data.
Cheers!
On prod environment I got this error:
fatal: [192.168.50.8]: FAILED! => {"changed": false, "cmd": ["/var/www/project/bin/console", "hautelook_alice:doctrine:fixtures:load", "--no-interaction"], "delta": "0:00:00.080143", "end": "2018-05-10 10:27:36.079665", "msg": "non-zero return code", "rc": 1, "start": "2018-05-10 10:27:35.999522", "stderr": "\n \n [Symfony\\Component\\Console\\Exception\\CommandNotFoundException] \n There are no commands defined in the \"hautelook_alice:doctrine:fixtures\" namespace. \n Did you mean this? \n generate:doctrine
Thats because of dev dependencies in composer.json, I believe. With commented SYMFONY_ENV: "{{ symfony_env|lower }}" or dev as environment in prompt everything works fine.
NB: this error will be removed by conditional logic in a next chapter.
Hey toporovvv ,
Yes, most probably so... but to be sure you can open config/bundles.php file (app/AppKernel.php) and make sure this fixtures bundle is loaded in dev/test env only (not in prod). Actually, it's a best practice to not load fixtures in production which makes sense because you can accidentally overwrite prod data.
Cheers!
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*", // v3.1.4
"doctrine/orm": "^2.5", // v2.7.2
"doctrine/doctrine-bundle": "^1.6", // 1.6.4
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // 2.11.1
"symfony/polyfill-apcu": "^1.0", // v1.2.0
"sensio/distribution-bundle": "^5.0", // v5.0.12
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.0
"snc/redis-bundle": "^2.0", // 2.0.0
"predis/predis": "^1.1", // v1.1.1
"composer/package-versions-deprecated": "^1.11" // 1.11.99
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.8
"symfony/phpunit-bridge": "^3.0", // v3.1.4
"doctrine/data-fixtures": "^1.1", // 1.3.3
"hautelook/alice-bundle": "^1.3" // v1.4.1
}
}
Hi!
I've a problem with environment the SYMFONY_ENV var. In my case I've called app_env instance of symfony_env. But when composer install --no-dev there is a error
TASK [Install Composer's dependencies] ***********
\n An error occurred when executing the \"'cache:clear --no-warmup'\" command: \n PHP Fatal error: Uncaught ReflectionException: Class Doctrine\Common\DataFixtures\AbstractFixture not found in /var/www/project/src/AppBundle/DataFixtures/ORM/LoadUserData.php:10
My playbook:
My project use doctrine:fixtures:load. As the docs say, I register the bundle in:
Do you know any idea that it can be ...? 😞
thanks!