Upgrading Recipes: New Commands!
Fun fact time! When you start a brand new Symfony project, behind the scenes, what you're actually doing is cloning this repository: symfony/skeleton
. Yep, your app literally starts as a single composer.json
file. But as soon as Composer installs your dependencies, the app is suddenly filled with a few directories and about 15 files.
All Config Files Come from a Recipe
All of those things are added by different recipes. So even the most "core" files - for example, public/index.php
, the file that our web server executes, is added by a recipe!
// ... lines 1 - 2 | |
use App\Kernel; | |
use Symfony\Component\Debug\Debug; | |
use Symfony\Component\HttpFoundation\Request; | |
require dirname(__DIR__).'/config/bootstrap.php'; | |
if ($_SERVER['APP_DEBUG']) { | |
umask(0000); | |
Debug::enable(); | |
} | |
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { | |
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); | |
} | |
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) { | |
Request::setTrustedHosts([$trustedHosts]); | |
} | |
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); | |
$request = Request::createFromGlobals(); | |
$response = $kernel->handle($request); | |
$response->send(); | |
$kernel->terminate($request, $response); |
We pretty much never need to look inside here or do anything, even though it's critical to our app working.
Another example is config/bootstrap.php
:
// ... lines 1 - 2 | |
use Symfony\Component\Dotenv\Dotenv; | |
require dirname(__DIR__).'/vendor/autoload.php'; | |
// Load cached env vars if the .env.local.php file exists | |
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2) | |
if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { | |
$_SERVER += $env; | |
$_ENV += $env; | |
} elseif (!class_exists(Dotenv::class)) { | |
throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); | |
} else { | |
$path = dirname(__DIR__).'/.env'; | |
$dotenv = new Dotenv(); | |
// load all the .env files | |
if (method_exists($dotenv, 'loadEnv')) { | |
$dotenv->loadEnv($path); | |
} else { | |
// fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added) | |
if (file_exists($path) || !file_exists($p = "$path.dist")) { | |
$dotenv->load($path); | |
} else { | |
$dotenv->load($p); | |
} | |
if (null === $env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) { | |
$dotenv->populate(array('APP_ENV' => $env = 'dev')); | |
} | |
if ('test' !== $env && file_exists($p = "$path.local")) { | |
$dotenv->load($p); | |
$env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env; | |
} | |
if (file_exists($p = "$path.$env")) { | |
$dotenv->load($p); | |
} | |
if (file_exists($p = "$path.$env.local")) { | |
$dotenv->load($p); | |
} | |
} | |
} | |
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; | |
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; | |
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; |
the boring, low-level file that initializes and normalizes environment variables. It's important that all Symfony projects have the same version of this file. If they didn't, some apps might work different than others... even if they have the same version of Symfony. Think of trying to write documentation for thousands of projects that all work a little bit differently. It's literally my nightmare.
All of the configuration files were also originally added by recipes. For example, cache.yaml
comes from the recipe for symfony/framework-bundle
:
framework: | |
cache: | |
// ... lines 3 - 13 | |
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) | |
app: '%cache_adapter%' | |
# Namespaced pools use the above "app" backend by default | |
pools: | |
cache.flysystem.psr6: | |
adapter: cache.app |
Why Recipes Update
Over time, the recipes themselves tend to change. If we installed the symfony/framework-bundle
today, it might give us a slightly different cache.yaml
file.
There are three reasons that a recipe might change. First, someone might update a recipe just because they want to add more examples or add some documentation comments to a config file. Those changes... aren't super important.
Or, second, someone might update a configuration file inside a recipe to activate a new feature that's probably from a new version of that library. These changes aren't critical to know about... but it is nice to know if a great new feature is suddenly available. We saw that a few minutes ago when the updated MonologBundle recipe told us about a cool option for filtering logs by status code.
The third reason a recipe might update is because something needs to be fixed, or we decide that we want to change some significant behavior. These changes are important.
Let me give you an example: during the first year after Symfony 4.0, several small but meaningful tweaks were made to the bootstrap.php
file to make sure that environment variables have just the right behavior. If you started your project on Symfony 4.0 and never "updated" the bootstrap.php
file, your app will be handling environment variables in a different way than other apps. That's... not great: we want our bootstrap.php
file to look exactly like it should.
New Recipe Commands!
A few minutes ago, when we did all the composer updating stuff, one of the packages that we upgraded was symfony/flex
itself: we upgraded it to 1.6.0
:
{ | |
// ... lines 2 - 3 | |
"require": { | |
// ... lines 5 - 24 | |
"symfony/flex": "^1.0", | |
// ... lines 26 - 43 | |
}, | |
// ... lines 45 - 102 | |
} |
Well guess what?! Starting in Flex 1.6.0
, there are some brand new fancy, amazing, incredible commands inside Composer to help inspect & upgrade recipes. It still takes a little bit of work and care, but the process is now very possible. A big thanks to community member and friend maxhelias who really helped to get this done.
Let's go check them out! Move over to your terminal and run:
composer recipes
Cool! This lists every recipe that we have installed and whether or not there is an update available. Heck, it will even show you if a package that's installed has a recipe that you're missing - maybe because it was added later.
Because my project was originally created on Symfony 4.0, it's fairly old and a lot of recipes have updates. The recipe system is also relatively new, so I think there were more updates during the first 2 years of that system than there will be in the next two years. We've got some work to do. Of course, we could just ignore these recipe updates... but we're risking our app not working quite right or missing info about new features.
Inspecting the twig/extension Recipe
Let's look at one of these more closely. How about twig/extensions
. This is not a particularly important library, but it's a nice one to start with. Run:
composer recipes twig/extensions
to see more details. Interesting: it has a link to the installed version of the recipe. Let's go check that out in the browser. Paste and... this is what the recipe looked like the moment we installed it. We can also go grab the URL to see what the latest version of the recipe looks like.
Check out the commit history. The version of the recipe we have installed has a commit hash starting with c986
. Back on the history, hey! That commit is right here! So this recipe is out of date, but the only change that's been made is this one commit. Inside it... search for twig/extensions
to find its changes. Ha! It's totally superficial: we changed from using tilde (~
) to null
... but just for clarity: those are equivalent in YAML.
Yep! The update to twig/extension
is not important at all. We could still update it - and I'll show you how next. But I'm going to skip it for now. Because... this is a tutorial about upgrading Symfony! So I want to focus on upgrading the recipes for everything that starts with symfony/
.
Let's start that process next by focusing on, surprisingly, one of the most important recipes: symfony/console
.
So I'm confused. Will 'composer recipes' only work properly if you have upgraded to 5.0?
I do not see '(Update Available)' next to any recipe in my Symfony 4.4 project, but if I run
composer recipe:install symfony/console --force -v
, bootstrap.php and console files update. symfony.lock indicates change from version 4.3.9 to 4.4.4.When I run
composer recipes symfony/console
I see:`
name : symfony/console
version : 4.4.4
status : auto-generated recipe
files :
├──bin
│ └──console
└──config
└──bootstrap.php
`
No indication of installed or current. All of the installed recipes provide similar results. All status = 'auto-generated recipe'.
Composer version 1.9.3 2020-02-04 12:58:49
Symfony Version 4.4
<blockquote>antishov/doctrine-extensions-bundle v1.4.2 Forked from stof/doctrine-extensions-bundle integration of the gedmo/doctrine-extensions with Symfony 4
behat/transliterator v1.3.0 String transliterator
doctrine/annotations v1.8.0 Docblock Annotations Parser
doctrine/cache 1.10.0 PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as ...
doctrine/collections 1.6.4 PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common 2.12.0 PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projec...
doctrine/data-fixtures 1.4.2 Data Fixtures for all Doctrine Object Managers
doctrine/dbal v2.10.1 Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and ma...
doctrine/doctrine-bundle 2.0.7 Symfony DoctrineBundle
doctrine/doctrine-fixtures-bundle 3.3.0 Symfony DoctrineFixturesBundle
doctrine/doctrine-migrations-bundle 2.1.2 Symfony DoctrineMigrationsBundle
doctrine/event-manager 1.1.0 The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrin...
doctrine/inflector 1.3.1 Common String Manipulations with regard to casing and singular/plural rules.
doctrine/instantiator 1.3.0 A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer 1.2.0 PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations 2.2.1 PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (D...
doctrine/orm v2.7.0 Object-Relational-Mapper for PHP
doctrine/persistence 1.3.6 The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctri...
doctrine/reflection v1.1.0 The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some ...
easycorp/easy-log-handler v1.0.9 A handler for Monolog that optimizes log messages to be processed by humans instead of software. Improve y...
egulias/email-validator 2.1.15 A library for validating emails against several RFCs
eightpoints/guzzle-bundle v7.6.1 Integrates Guzzle 6.x, a PHP HTTP Client, into Symfony 2/3/4. Comes with easy and powerful configuration o...
erusev/parsedown 1.7.4 Parser for Markdown.
friendsofsymfony/ckeditor-bundle 2.2.0 Provides a CKEditor integration for your Symfony project.
friendsofsymfony/jsrouting-bundle 2.5.3 A pretty nice way to expose your Symfony2 routing to client applications.
fzaninotto/faker v1.9.1 Faker is a PHP library that generates fake data for you.
gedmo/doctrine-extensions v2.4.39 Doctrine2 behavioral extensions
guzzlehttp/guzzle 6.5.2 Guzzle is a PHP HTTP client library
guzzlehttp/promises v1.3.1 Guzzle promises library
guzzlehttp/psr7 1.6.1 PSR-7 message implementation that also provides common utility methods
jdorn/sql-formatter v1.2.17 a PHP SQL highlighting library
monolog/monolog 1.25.3 Sends your logs to files, sockets, inboxes, databases and various web services
nikic/php-parser v4.3.0 A PHP parser written in PHP
ocramius/package-versions 1.4.2 Composer plugin that provides efficient querying for installed package versions (no runtime IO)
ocramius/proxy-manager 2.2.3 A library providing utilities to generate, instantiate and generally operate with Object Proxies
phing/phing 2.16.3 PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.
phpdocumentor/reflection-common 2.0.0 Common reflection classes used by phpdocumentor to reflect the code structure
phpdocumentor/reflection-docblock 4.3.4 With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve inf...
phpdocumentor/type-resolver 1.0.1 A PSR-5 based resolver of Class names, Types and Structural Element Names
psr/cache 1.0.1 Common interface for caching libraries
psr/container 1.0.0 Common Container Interface (PHP FIG PSR-11)
psr/http-message 1.0.1 Common interface for HTTP messages
psr/link 1.0.0 Common interfaces for HTTP links
psr/log 1.1.2 Common interface for logging libraries
ralouphie/getallheaders 3.0.3 A polyfill for getallheaders.
sensio/framework-extra-bundle v5.5.3 This bundle provides a way to configure your controllers with annotations
symfony/asset v4.4.4 Symfony Asset Component
symfony/browser-kit v4.4.4 Symfony BrowserKit Component
symfony/cache v4.4.4 Symfony Cache component with PSR-6, PSR-16, and tags
symfony/cache-contracts v2.0.1 Generic abstractions related to caching
symfony/config v4.4.4 Symfony Config Component
symfony/console v4.4.4 Symfony Console Component
symfony/css-selector v4.4.4 Symfony CssSelector Component
symfony/debug v4.4.4 Symfony Debug Component
symfony/debug-bundle v4.4.4 Symfony DebugBundle
symfony/debug-pack v1.0.7 A debug pack for Symfony projects
symfony/dependency-injection v4.4.4 Symfony DependencyInjection Component
symfony/doctrine-bridge v4.4.4 Symfony Doctrine Bridge
symfony/dom-crawler v4.4.4 Symfony DomCrawler Component
symfony/dotenv v4.4.4 Registers environment variables from a .env file
symfony/error-handler v4.4.4 Symfony ErrorHandler Component
symfony/event-dispatcher v4.4.4 Symfony EventDispatcher Component
symfony/event-dispatcher-contracts v1.1.7 Generic abstractions related to dispatching event
symfony/expression-language v4.4.4 Symfony ExpressionLanguage Component
symfony/filesystem v4.4.4 Symfony Filesystem Component
symfony/finder v4.4.4 Symfony Finder Component
symfony/flex v1.6.2 Composer plugin for Symfony
symfony/form v4.4.4 Symfony Form Component
symfony/framework-bundle v4.4.4 Symfony FrameworkBundle
symfony/http-client v4.4.4 Symfony HttpClient component
symfony/http-client-contracts v2.0.1 Generic abstractions related to HTTP clients
symfony/http-foundation v4.4.4 Symfony HttpFoundation Component
symfony/http-kernel v4.4.4 Symfony HttpKernel Component
symfony/inflector v4.4.4 Symfony Inflector Component
symfony/intl v4.4.4 A PHP replacement layer for the C intl extension that includes additional data from the ICU library.
symfony/mailer v4.4.4 Symfony Mailer Component
symfony/maker-bundle v1.14.3 Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget...
symfony/mime v4.4.4 A library to manipulate MIME messages
symfony/monolog-bridge v4.4.4 Symfony Monolog Bridge
symfony/monolog-bundle v3.5.0 Symfony MonologBundle
symfony/options-resolver v4.4.4 Symfony OptionsResolver Component
symfony/orm-pack v1.0.8 A pack for the Doctrine ORM
symfony/phpunit-bridge v5.0.4 Symfony PHPUnit Bridge
symfony/polyfill-ctype v1.13.1 Symfony polyfill for ctype functions
symfony/polyfill-intl-icu v1.13.1 Symfony polyfill for intl's ICU-related data and classes
symfony/polyfill-intl-idn v1.13.1 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions
symfony/polyfill-mbstring v1.13.1 Symfony polyfill for the Mbstring extension
symfony/polyfill-php72 v1.13.1 Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/polyfill-php73 v1.13.1 Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions
symfony/process v4.4.4 Symfony Process Component
symfony/profiler-pack v1.0.4 A pack for the Symfony web profiler
symfony/property-access v4.4.4 Symfony PropertyAccess Component
symfony/property-info v4.4.4 Symfony Property Info Component
symfony/routing v4.4.4 Symfony Routing Component
symfony/security-bundle v4.4.4 Symfony SecurityBundle
symfony/security-core v4.4.4 Symfony Security Component - Core Library
symfony/security-csrf v4.4.4 Symfony Security Component - CSRF Library
symfony/security-guard v4.4.4 Symfony Security Component - Guard
symfony/security-http v4.4.4 Symfony Security Component - HTTP Integration
symfony/serializer v4.4.4 Symfony Serializer Component
symfony/serializer-pack v1.0.2 A pack for the Symfony serializer
symfony/service-contracts v2.0.1 Generic abstractions related to writing services
symfony/stopwatch v4.4.4 Symfony Stopwatch Component
symfony/test-pack v1.0.6 A pack for functional and end-to-end testing within a Symfony app
symfony/translation v4.4.4 Symfony Translation Component
symfony/translation-contracts v2.0.1 Generic abstractions related to translation
symfony/twig-bridge v4.4.4 Symfony Twig Bridge
symfony/twig-bundle v4.4.4 Symfony TwigBundle
symfony/twig-pack v1.0.0 A Twig pack for Symfony projects
symfony/validator v4.4.4 Symfony Validator Component
symfony/var-dumper v4.4.4 Symfony mechanism for exploring and dumping PHP variables
symfony/var-exporter v4.4.4 A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code
symfony/web-link v4.4.4 Symfony WebLink Component
symfony/web-profiler-bundle v4.4.4 Symfony WebProfilerBundle
symfony/web-server-bundle v4.4.4 Symfony WebServerBundle
symfony/webpack-encore-bundle v1.7.3 Integration with your Symfony app & Webpack Encore!
symfony/yaml v4.4.4 Symfony Yaml Component
twig/extra-bundle v3.0.3 A Symfony bundle for extra Twig extensions
twig/markdown-extra v3.0.3 A Twig extension for Markdown
twig/twig v3.0.3 Twig, the flexible, fast, and secure template language for PHP
webmozart/assert 1.6.0 Assertions to validate method input/output with nice error messages.
willdurand/jsonp-callback-validator v1.1.0 JSONP callback validator.
zendframework/zend-code 3.4.1 Extensions to the PHP Reflection API, static code scanning, and code generation
zendframework/zend-eventmanager 3.2.1 Trigger and listen to events within a PHP application
</blockquote>