Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Installing Flex

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Our project is now on Symfony 4.0, and it still works! Well, it almost works: we would just need to remove a few references to SensioDistributionBundle and SensioGeneratorBundle.

The point is this: if you want, you can upgrade to Symfony 4, but not migrate to the new Flex project structure. That's fine.

But... since Flex is awesome... let's do it!

Flex: Composer Plugin & New BFF

Flex is a Composer plugin, and, it's pretty simple: when you install a package, it checks to see if there is a recipe for that package. A recipe can add configuration files, auto-enable the bundle, add paths to your .gitignore file and more. But, for Flex to work, you need to use the Flex directory structure.

Upgrade to Flex: The Plan

So here's the plan: we're going to bootstrap a new Flex application right inside our existing project. Then, little-by-little, we'll move our code and configuration into it. It's going to be pretty freakin' cool.

Upgrade Composer. For Real

Before we start, make sure that your Composer is at the latest version:

composer self-update

Seriously, do this. Composer recently released a bug fix that helps Flex.

Installing Flex

Ok, so... let's install Flex!

composer require symfony/flex

As soon as this is in our project, it will find and install recipes each time we add a new library to our project. In fact, check it out!

Configuring symfony/flex

Ha! Flex even installed a recipe for itself! What an over-achiever! Let's find out what it did:

git status

Of course, it modified composer.json and composer.lock. But there are two new files: .env.dist and symfony.lock. Open the first.

How did this get here? It was added by the symfony/flex recipe! More about this file later.

Next, look at symfony.lock. This file is managed by Flex: it keeps track of which recipes were installed. You should commit it, but not think about it.

Installing Missing Recipes

Because this is an existing project, our app already contains a bunch of vendor libraries... and a lot of these might have recipes that were never installed because Flex wasn't in our project yet! Lame! No problem! Empty the vendor/ directory and run composer install

rm -rf vendor
composer install

Normally, Flex only installs a recipe when you first composer require a library. But Flex knows that the recipes for these libraries were never installed. So it runs them now.

Yea! 11 recipes! Woh! And one of them is from the "contrib" repository. There are two repositories for recipes. The official one is heavily guarded for quality. The "contrib" one also has some checks, but the quality is not guaranteed. That's why you see this question. I'll type "p" to permanently allow recipes from contrib.

Run git status to see what changed:

git status

Woh! We have a new config/ directory and a lot more! Starting with nothing, Flex is scaffolding the new project around us! It's even auto-enabling all the bundles in a new bundles.php file.

Sweet!

The Flex composer.json

When you start a new Flex project, you actually clone this symfony/skeleton repository... which is literally one file: composer.json. This has a few really important things in it, including the fact that it requires symfony/framework-bundle but not symfony/symfony.

Let's work on that next!

Leave a comment!

11
Login or Register to join the conversation
CDesign Avatar
CDesign Avatar CDesign | posted 4 years ago | edited

At the beginning of this chapter, Ryan says the new Sym4 app still works. But I am getting this error when trying to load the homepage (even after removing the two lines from AppKernel.php):

Error: Class AppBundle\Security\LoginFormAuthenticator contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Symfony\Component\Security\Guard\AuthenticatorInterface::onAuthenticationSuccess)

It looks like something has changed in Guard Authenticator. Is this something that is addressed later in the tutorial? Or should I get it fixed now before trying to install Flex?

Reply
CDesign Avatar

So.. the answer is just keep going. Ryan addresses this issue in Chapter 09.

1 Reply
Vladimir Z. Avatar
Vladimir Z. Avatar Vladimir Z. | posted 5 years ago | edited

Hello, Ryan!
When I installed Flex, it converted my <strong>phpunit.xml.dist</strong> to this:


<?xml version="1.0" encoding="UTF-8"?>

<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="app/autoload.php"
>
    <php>
        <ini name="error_reporting" value="-1" />

        <!-- ###+ doctrine/doctrine-bundle ### -->
        <!-- Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -->
        <!-- For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" -->
        <!-- Configure your db driver and server_version in config/packages/doctrine.yaml -->
        <env name="DATABASE_URL" value="mysql://db_user:db_password@127.0.0.1:3306/db_name"/>
        <!-- ###- doctrine/doctrine-bundle ### -->

        <!-- ###+ symfony/swiftmailer-bundle ### -->
        <!-- For Gmail as a transport, use: "gmail://username:password@localhost" -->
        <!-- For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" -->
        <!-- Delivery is disabled by default via "null://localhost" -->
        <env name="MAILER_URL" value="null://localhost"/>
        <!-- ###- symfony/swiftmailer-bundle ### -->

        <!-- ###+ symfony/framework-bundle ### -->
        <env name="APP_ENV" value="dev"/>
        <env name="APP_SECRET" value="5f0bab9ed6fbf020425f21cffc2704c9"/>
        <!-- env name="TRUSTED_PROXIES" value="127.0.0.1,127.0.0.2" -->
        <!-- env name="TRUSTED_HOSTS" value="localhost,example.com" -->
        <!-- ###- symfony/framework-bundle ### -->

        <!-- ###+ lexik/jwt-authentication-bundle ### -->
        <!-- Key paths should be relative to the project directory -->
        <env name="JWT_PRIVATE_KEY_PATH" value="config/jwt/private.pem"/>
        <env name="JWT_PUBLIC_KEY_PATH" value="config/jwt/public.pem"/>
        <env name="JWT_PASSPHRASE" value="86c79d44541ebfb81f323ed06a3f0f65"/>
        <!-- ###- lexik/jwt-authentication-bundle ### -->
    </php>

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

    <php>
        <server name="KERNEL_DIR" value="app/" />

        <!-- ###+ doctrine/doctrine-bundle ### -->
        <!-- Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -->
        <!-- For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" -->
        <!-- Configure your db driver and server_version in config/packages/doctrine.yaml -->
        <env name="DATABASE_URL" value="mysql://db_user:db_password@127.0.0.1:3306/db_name"/>
        <!-- ###- doctrine/doctrine-bundle ### -->

        <!-- ###+ symfony/swiftmailer-bundle ### -->
        <!-- For Gmail as a transport, use: "gmail://username:password@localhost" -->
        <!-- For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" -->
        <!-- Delivery is disabled by default via "null://localhost" -->
        <env name="MAILER_URL" value="null://localhost"/>
        <!-- ###- symfony/swiftmailer-bundle ### -->

        <!-- ###+ symfony/framework-bundle ### -->
        <env name="APP_ENV" value="dev"/>
        <env name="APP_SECRET" value="5f0bab9ed6fbf020425f21cffc2704c9"/>
        <!-- env name="TRUSTED_PROXIES" value="127.0.0.1,127.0.0.2" -->
        <!-- env name="TRUSTED_HOSTS" value="localhost,example.com" -->
        <!-- ###- symfony/framework-bundle ### -->

        <!-- ###+ lexik/jwt-authentication-bundle ### -->
        <!-- Key paths should be relative to the project directory -->
        <env name="JWT_PRIVATE_KEY_PATH" value="config/jwt/private.pem"/>
        <env name="JWT_PUBLIC_KEY_PATH" value="config/jwt/public.pem"/>
        <env name="JWT_PASSPHRASE" value="86c79d44541ebfb81f323ed06a3f0f65"/>
        <!-- ###- lexik/jwt-authentication-bundle ### -->
    </php>

    <filter>
        <whitelist>
            <directory>src</directory>
            <exclude>
                <directory>src/*Bundle/Resources</directory>
                <directory>src/*/*Bundle/Resources</directory>
                <directory>src/*/Bundle/*Bundle/Resources</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

However, when starting a new Symfony4 project from scratch and installing PHPUnit in it, I get the following <strong>phpunit.xml.dist</strong>


<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.1/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="vendor/autoload.php"
>
    <php>
        <ini name="error_reporting" value="-1" />
        <env name="KERNEL_CLASS" value="App\Kernel" />
        <env name="APP_ENV" value="test" />
        <env name="APP_DEBUG" value="1" />
        <env name="APP_SECRET" value="s$cretf0rt3st" />
        <env name="SHELL_VERBOSITY" value="-1" />
        <!-- define your env variables for the test env here -->
    </php>

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./src/</directory>
        </whitelist>
    </filter>

    <listeners>
        <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
    </listeners>
</phpunit>

My question is why is the top one different from the bottom and why does the top one contain 2 mostly identical sections above and below


    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

Thank you!

Reply

Hey Vladimir Z.!

GREAT question :). And, there are 2 things going on:

1) Currently, when you run tests in a Symfony 4 / Flex project, it does NOT read your .env file. Instead, you're supposed to duplicate your environment variables in your phpunit.xml.dist file. That will likely change (I'm changing it, because it's annoying: https://github.com/symfony/..., but that's the current state of things. So, because of this, when Flex installs a recipe, and that recipe adds a new environment variable, it adds it to .env, .env.dist AND to phpunit.xml.dist. This is what you're seeing: the recipe causes these changes.

2) BUT, there's also the duplication. This should not happen - it smells like some sort of Flex bug to me, tbh - because you had an existing phpunit.xml.dist file and were upgrading to Flex, this may have caused some situation that is not currently accounted for. Definitely remove that duplication. If you know the steps to replicate, you could definitely open an issue on Symfony Flex for that: https://github.com/symfony/.... I would be happy to support that issue, as I think it's valid. However, we *may*/probably will remove this phpunit.xml.dist functionality soon anyways (via my linked PR - just need to finish it!).

Cheers!

Reply
Vladimir Z. Avatar
Vladimir Z. Avatar Vladimir Z. | weaverryan | posted 5 years ago | edited

Hi weaverryan!

The duplication in phpunit.xml.dist can be replicated by simply following your Upgrade to Symfony4 and Flex!
tutorial. It happens when Flex gets installed.

Would you suggest removing the duplication or dumping this phpunit.xml.dist file altogether and simply going with a fresh one that is created when PHPUnit is first installed? In this case, how would I "feed" the test environmental variables? Would I put them into the test YAML files, or will they be read from .env?

Thanks!

Reply

Hey Vladimir Z.

I would stick with the file that comes from installing Symfony4 (the short one), and then add all the "env" variables that my project needs


<php>
        <env name="SOME_API_KEY" value="secret_key"/>        
</php>

Cheers!

Reply
Vladimir Z. Avatar

¡Hola, Diego!
Say, I want to store my test environmental variables in the .env file as well. How can I "feed" them into the phpunit.xml.dist file instead of declaring with there with the <env name="..." value=".../"> ?
Or does it read them automatically from the .env file and the variables added to the phpunit.xml.dist file directly simply overwrite them?
Gracias.

Reply

Hola! como estas? :)

I'm afraid that you have to manually add them to both files: .env and phpunit.xml.dist
As Ryan said, this is an annoying thing to do but Symfony people is working on to get it better

Reply
Vladimir Z. Avatar

Is there any way to somehow read them from .env in phpunit.xml.dist? Like using the env() function in the YAML files?

Reply

Vladimir Z. yep! For now, you can "mimic" my PR and create a tests/bootstrap.php - https://github.com/symfony/.... It's a super simple change to your project, and will get you what you need. Then, soon, everyone will hopefully be using a similar approach anyways :)

Reply
Vladimir Z. Avatar

Thank you, Ryan! Will Try this.

5 Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/doctrine-bundle": "^1.6", // 1.8.1
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.2
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.1
        "doctrine/orm": "^2.5", // v2.7.2
        "fzaninotto/faker": "^1.7", // v1.7.1
        "knplabs/knp-markdown-bundle": "^1.4", // 1.6.0
        "sensio/framework-extra-bundle": "^5.0", // v5.1.3
        "stof/doctrine-extensions-bundle": "dev-master", // dev-master
        "symfony/asset": "^4.0", // v4.0.1
        "symfony/console": "^4.0", // v4.0.1
        "symfony/flex": "^1.0", // v1.9.10
        "symfony/form": "^4.0", // v4.0.1
        "symfony/framework-bundle": "^4.0", // v4.0.1
        "symfony/lts": "^4@dev", // dev-master
        "symfony/maker-bundle": "^1.0", // v1.0.2
        "symfony/monolog-bundle": "^3.1", // v3.1.2
        "symfony/polyfill-apcu": "^1.0", // v1.6.0
        "symfony/profiler-pack": "^1.0", // v1.0.3
        "symfony/security-bundle": "^4.0", // v4.0.1
        "symfony/security-csrf": "^4.0",
        "symfony/swiftmailer-bundle": "^3.1", // v3.1.6
        "symfony/translation": "^4.0", // v4.0.1
        "symfony/twig-bundle": "^4.0", // v4.0.1
        "symfony/validator": "^4.0", // v4.0.1
        "symfony/web-server-bundle": "^4.0", // v4.0.1
        "symfony/yaml": "^4.0" // v4.0.1
    },
    "require-dev": {
        "symfony/dotenv": "^4.0", // v4.0.1
        "symfony/phpunit-bridge": "^4.0", // v4.0.1
        "doctrine/doctrine-fixtures-bundle": "^3.0" // 3.0.2
    }
}
userVoice