diff --git a/configuration/dot-env-changes.rst b/configuration/dot-env-changes.rst index 89844d991b1..7386a05966f 100644 --- a/configuration/dot-env-changes.rst +++ b/configuration/dot-env-changes.rst @@ -55,17 +55,18 @@ changes can be made to any Symfony 3.4 or higher app: #. Update ``.gitignore``: .. code-block:: diff + :dedent: 0 - # .gitignore - # ... + # .gitignore + # ... - ###> symfony/framework-bundle ### + ###> symfony/framework-bundle ### - /.env + /.env.local + /.env.local.php + /.env.*.local - # ... + # ... #. Rename ``.env`` to ``.env.local`` and ``.env.dist`` to ``.env``: diff --git a/controller.rst b/controller.rst index a5017452832..d17d719f1ac 100644 --- a/controller.rst +++ b/controller.rst @@ -97,17 +97,18 @@ Add the ``use`` statement atop your controller class and then modify ``LuckyController`` to extend it: .. code-block:: diff + :dedent: 0 - // src/Controller/LuckyController.php - namespace App\Controller; + // src/Controller/LuckyController.php + namespace App\Controller; + use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - class LuckyController + class LuckyController extends AbstractController - { - // ... - } + { + // ... + } That's it! You now have access to methods like :ref:`$this->render() ` and many others that you'll learn about next. diff --git a/doctrine.rst b/doctrine.rst index f44a1c36ff1..e5707f59f33 100644 --- a/doctrine.rst +++ b/doctrine.rst @@ -279,21 +279,22 @@ This adds the new ``description`` property and ``getDescription()`` and ``setDes methods: .. code-block:: diff + :dedent: 0 - // src/Entity/Product.php - // ... + // src/Entity/Product.php + // ... - class Product - { - // ... + class Product + { + // ... + /** + * @ORM\Column(type="text") + */ + private $description; - // getDescription() & setDescription() were also added - } + // getDescription() & setDescription() were also added + } The new property is mapped, but it doesn't exist yet in the ``product`` table. No problem! Generate a new migration: diff --git a/frontend/encore/cdn.rst b/frontend/encore/cdn.rst index a7a2884c13a..f0d648d1ffe 100644 --- a/frontend/encore/cdn.rst +++ b/frontend/encore/cdn.rst @@ -5,16 +5,17 @@ Are you deploying to a CDN? That's awesome :) Once you've made sure that your built files are uploaded to the CDN, configure it in Encore: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - .setOutputPath('public/build/') - // in dev mode, don't use the CDN - .setPublicPath('/build'); - // ... - ; + Encore + .setOutputPath('public/build/') + // in dev mode, don't use the CDN + .setPublicPath('/build'); + // ... + ; + if (Encore.isProduction()) { + Encore.setPublicPath('https://my-cool-app.com.global.prod.fastly.net'); diff --git a/frontend/encore/copy-files.rst b/frontend/encore/copy-files.rst index 28e8f26d80a..5925450afd5 100644 --- a/frontend/encore/copy-files.rst +++ b/frontend/encore/copy-files.rst @@ -31,12 +31,13 @@ Webpack - like a template - you can use the ``copyFiles()`` method to copy those files into your final output directory. .. code-block:: diff + :dedent: 0 - // webpack.config.js + // webpack.config.js - Encore - // ... - .setOutputPath('public/build/') + Encore + // ... + .setOutputPath('public/build/') + .copyFiles({ + from: './assets/images', diff --git a/frontend/encore/custom-loaders-plugins.rst b/frontend/encore/custom-loaders-plugins.rst index 66ce1f7c5cc..967129d226d 100644 --- a/frontend/encore/custom-loaders-plugins.rst +++ b/frontend/encore/custom-loaders-plugins.rst @@ -49,15 +49,16 @@ via the ``addPlugin()`` method. For example, if you use `Moment.js`_, you might to use the `IgnorePlugin`_ (see `moment/moment#2373`_): .. code-block:: diff + :dedent: 0 - // webpack.config.js + // webpack.config.js + var webpack = require('webpack'); - Encore - // ... + Encore + // ... + .addPlugin(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)) - ; + ; .. _`handlebars-loader`: https://github.com/pcardune/handlebars-loader .. _`plugins`: https://webpack.js.org/plugins/ diff --git a/frontend/encore/dev-server.rst b/frontend/encore/dev-server.rst index b1f72e5996b..d0c6fcbbbf3 100644 --- a/frontend/encore/dev-server.rst +++ b/frontend/encore/dev-server.rst @@ -65,13 +65,14 @@ you'll need to also tell the dev-server to use HTTPS. To do this, you can reuse server SSL certificate: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... + const path = require('path'); - Encore - // ... + Encore + // ... + .configureDevServerOptions(options => { + options.https = { diff --git a/frontend/encore/faq.rst b/frontend/encore/faq.rst index c6c6d86c257..6999fd424c4 100644 --- a/frontend/encore/faq.rst +++ b/frontend/encore/faq.rst @@ -62,12 +62,13 @@ If your app does not live at the root of your web server (i.e. it lives under a like ``/myAppSubdir``), you will need to configure that when calling ``Encore.setPublicPath()``: .. code-block:: diff + :dedent: 0 - // webpack.config.js - Encore - // ... + // webpack.config.js + Encore + // ... - .setOutputPath('public/build/') + .setOutputPath('public/build/') - .setPublicPath('/build') + // this is your *true* public path @@ -76,7 +77,7 @@ like ``/myAppSubdir``), you will need to configure that when calling ``Encore.se + // this is now needed so that your manifest.json keys are still `build/foo.js` + // (which is a file that's used by Symfony's `asset()` function) + .setManifestKeyPrefix('build') - ; + ; If you're using the ``encore_entry_script_tags()`` and ``encore_entry_link_tags()`` Twig shortcuts (or are :ref:`processing your assets through entrypoints.json ` diff --git a/frontend/encore/legacy-applications.rst b/frontend/encore/legacy-applications.rst index 4f1193d7e06..5660de4cd27 100644 --- a/frontend/encore/legacy-applications.rst +++ b/frontend/encore/legacy-applications.rst @@ -31,11 +31,12 @@ jQuery plugins often expect that jQuery is already available via the ``$`` or ``webpack.config.js`` file: .. code-block:: diff + :dedent: 0 - Encore - // ... + Encore + // ... + .autoProvidejQuery() - ; + ; After restarting Encore, Webpack will look for all uninitialized ``$`` and ``jQuery`` variables and automatically require ``jquery`` and set those variables for you. @@ -73,9 +74,10 @@ For example, in your ``app.js`` file that's processed by Webpack and loaded on e page, add: .. code-block:: diff + :dedent: 0 - // require jQuery normally - const $ = require('jquery'); + // require jQuery normally + const $ = require('jquery'); + // create global $ and jQuery variables + global.$ = global.jQuery = $; diff --git a/frontend/encore/postcss.rst b/frontend/encore/postcss.rst index d2322b14032..8d9a76d3ca1 100644 --- a/frontend/encore/postcss.rst +++ b/frontend/encore/postcss.rst @@ -27,13 +27,14 @@ Next, create a ``postcss.config.js`` file at the root of your project: Then, enable the loader in Encore! .. code-block:: diff + :dedent: 0 - // webpack.config.js + // webpack.config.js - Encore - // ... + Encore + // ... + .enablePostCssLoader() - ; + ; Because you just modified ``webpack.config.js``, stop and restart Encore. @@ -41,19 +42,20 @@ That's it! The ``postcss-loader`` will now be used for all CSS, Sass, etc files. You can also pass options to the `postcss-loader`_ by passing a callback: .. code-block:: diff + :dedent: 0 - // webpack.config.js + // webpack.config.js + const path = require('path'); - Encore - // ... + Encore + // ... + .enablePostCssLoader((options) => { + options.postcssOptions = { + // the directory where the postcss.config.js file is stored + config: path.resolve(__dirname, 'sub-dir', 'custom.config.js'), + }; + }) - ; + ; .. _browserslist_package_config: @@ -65,26 +67,28 @@ support. The best-practice is to configure this directly in your ``package.json` (so that all the tools can read this): .. code-block:: diff + :dedent: 0 - { + { + "browserslist": [ + "defaults" + ] - } + } The ``defaults`` option is recommended for most users and would be equivalent to the following browserslist: .. code-block:: diff + :dedent: 0 - { + { + "browserslist": [ + "> 0.5%", + "last 2 versions", + "Firefox ESR", + "not dead" + ] - } + } See `browserslist`_ for more details on the syntax. diff --git a/frontend/encore/reactjs.rst b/frontend/encore/reactjs.rst index ca3b017f13b..f7dd21096c6 100644 --- a/frontend/encore/reactjs.rst +++ b/frontend/encore/reactjs.rst @@ -16,14 +16,15 @@ Using React? First add some dependencies with Yarn: Enable react in your ``webpack.config.js``: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - // ... + Encore + // ... + .enableReactPreset() - ; + ; Then restart Encore. When you do, it will give you a command you can run to diff --git a/frontend/encore/simple-example.rst b/frontend/encore/simple-example.rst index cda018f36e8..65a34b95bfa 100644 --- a/frontend/encore/simple-example.rst +++ b/frontend/encore/simple-example.rst @@ -166,9 +166,10 @@ We'll use jQuery to print this message on the page. Install it via: Great! Use ``import`` to import ``jquery`` and ``greet.js``: .. code-block:: diff + :dedent: 0 - // assets/app.js - // ... + // assets/app.js + // ... + // loads the jquery package from node_modules + import jquery from 'jquery'; @@ -208,14 +209,15 @@ etc.). To handle this, create a new "entry" JavaScript file for each page: Next, use ``addEntry()`` to tell Webpack to read these two new files when it builds: .. code-block:: diff + :dedent: 0 - // webpack.config.js - Encore - // ... - .addEntry('app', './assets/app.js') + // webpack.config.js + Encore + // ... + .addEntry('app', './assets/app.js') + .addEntry('checkout', './assets/checkout.js') + .addEntry('account', './assets/account.js') - // ... + // ... And because you just changed the ``webpack.config.js`` file, make sure to stop and restart Encore: @@ -232,9 +234,10 @@ Finally, include the ``script`` and ``link`` tags on the individual pages where you need them: .. code-block:: diff + :dedent: 0 - {# templates/.../checkout.html.twig #} - {% extends 'base.html.twig' %} + {# templates/.../checkout.html.twig #} + {% extends 'base.html.twig' %} + {% block stylesheets %} + {{ parent() }} @@ -262,21 +265,23 @@ CSS you can also use Sass, LESS or Stylus. To use Sass, rename the ``app.css`` file to ``app.scss`` and update the ``import`` statement: .. code-block:: diff + :dedent: 0 - // assets/app.js + // assets/app.js - import './styles/app.css'; + import './styles/app.scss'; Then, tell Encore to enable the Sass pre-processor: .. code-block:: diff + :dedent: 0 - // webpack.config.js - Encore - // ... + // webpack.config.js + Encore + // ... + .enableSassLoader() - ; + ; Because you just changed your ``webpack.config.js`` file, you'll need to restart Encore. When you do, you'll see an error! diff --git a/frontend/encore/split-chunks.rst b/frontend/encore/split-chunks.rst index 5569a9731f3..0582aab4f3f 100644 --- a/frontend/encore/split-chunks.rst +++ b/frontend/encore/split-chunks.rst @@ -9,15 +9,16 @@ into additional files, which will contain "shared" code. To enable this, call ``splitEntryChunks()``: .. code-block:: diff + :dedent: 0 - Encore - // ... + Encore + // ... - // multiple entry files, which probably import the same code - .addEntry('app', './assets/app.js') - .addEntry('homepage', './assets/homepage.js') - .addEntry('blog', './assets/blog.js') - .addEntry('store', './assets/store.js') + // multiple entry files, which probably import the same code + .addEntry('app', './assets/app.js') + .addEntry('homepage', './assets/homepage.js') + .addEntry('blog', './assets/blog.js') + .addEntry('store', './assets/store.js') + .splitEntryChunks() @@ -52,11 +53,12 @@ The logic for *when* and *how* to split the files is controlled by the this plugin with the ``configureSplitChunks()`` function: .. code-block:: diff + :dedent: 0 - Encore - // ... + Encore + // ... - .splitEntryChunks() + .splitEntryChunks() + .configureSplitChunks(function(splitChunks) { + // change the configuration + splitChunks.minSize = 0; diff --git a/frontend/encore/typescript.rst b/frontend/encore/typescript.rst index b1af45d9c04..73225d70acf 100644 --- a/frontend/encore/typescript.rst +++ b/frontend/encore/typescript.rst @@ -4,21 +4,22 @@ Enabling TypeScript (ts-loader) Want to use `TypeScript`_? No problem! First, enable it: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - // ... + Encore + // ... + .addEntry('main', './assets/main.ts') + .enableTypeScriptLoader() - // optionally enable forked type script for faster builds - // https://www.npmjs.com/package/fork-ts-checker-webpack-plugin - // requires that you have a tsconfig.json file that is setup correctly. + // optionally enable forked type script for faster builds + // https://www.npmjs.com/package/fork-ts-checker-webpack-plugin + // requires that you have a tsconfig.json file that is setup correctly. + //.enableForkedTypeScriptTypesChecking() - ; + ; Then restart Encore. When you do, it will give you a command you can run to install any missing dependencies. After running that command and restarting @@ -29,10 +30,11 @@ also configure the `ts-loader options`_ via the ``enableTypeScriptLoader()`` method. .. code-block:: diff + :dedent: 0 - Encore - // ... - .addEntry('main', './assets/main.ts') + Encore + // ... + .addEntry('main', './assets/main.ts') - .enableTypeScriptLoader() + .enableTypeScriptLoader(function(tsConfig) { @@ -42,8 +44,8 @@ method. + // tsConfig.silent = false + }) - // ... - ; + // ... + ; See the `Encore's index.js file`_ for detailed documentation and check out the `tsconfig.json reference`_ and the `Webpack guide about Typescript`_. diff --git a/frontend/encore/versioning.rst b/frontend/encore/versioning.rst index 1f3d0cdd39e..2e7559f585c 100644 --- a/frontend/encore/versioning.rst +++ b/frontend/encore/versioning.rst @@ -11,13 +11,14 @@ instead of ``app.js``). This allows you to use aggressive caching strategies ignoring any existing cache: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - .setOutputPath('public/build/') - // ... + Encore + .setOutputPath('public/build/') + // ... + .enableVersioning() To link to these assets, Encore creates two files ``entrypoints.json`` and diff --git a/frontend/encore/virtual-machine.rst b/frontend/encore/virtual-machine.rst index 068d5c8451f..f365c42f132 100644 --- a/frontend/encore/virtual-machine.rst +++ b/frontend/encore/virtual-machine.rst @@ -48,15 +48,16 @@ If your Symfony application is running on a custom domain (e.g. ``package.json``: .. code-block:: diff + :dedent: 0 - { - ... - "scripts": { + { + ... + "scripts": { - "dev-server": "encore dev-server", + "dev-server": "encore dev-server --public http://app.vm:8080", - ... - } - } + ... + } + } After restarting Encore and reloading your web page, you will probably see different issues in the web console: @@ -77,15 +78,16 @@ Add the ``--host 0.0.0.0`` argument to the ``dev-server`` configuration in your connections: .. code-block:: diff + :dedent: 0 - { - ... - "scripts": { + { + ... + "scripts": { - "dev-server": "encore dev-server --public http://app.vm:8080", + "dev-server": "encore dev-server --public http://app.vm:8080 --host 0.0.0.0", - ... - } - } + ... + } + } .. caution:: @@ -99,15 +101,16 @@ Webpack will respond ``Invalid Host header`` when trying to access files from the dev-server. To fix this, add the argument ``--disable-host-check``: .. code-block:: diff + :dedent: 0 - { - ... - "scripts": { + { + ... + "scripts": { - "dev-server": "encore dev-server --public http://app.vm:8080 --host 0.0.0.0", + "dev-server": "encore dev-server --public http://app.vm:8080 --host 0.0.0.0 --disable-host-check", - ... - } - } + ... + } + } .. caution:: diff --git a/frontend/encore/vuejs.rst b/frontend/encore/vuejs.rst index eb8e2793c82..327a397ae04 100644 --- a/frontend/encore/vuejs.rst +++ b/frontend/encore/vuejs.rst @@ -9,16 +9,17 @@ Enabling Vue.js (``vue-loader``) Want to use `Vue.js`_? No problem! First enable it in ``webpack.config.js``: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - // ... - .addEntry('main', './assets/main.js') + Encore + // ... + .addEntry('main', './assets/main.js') + .enableVueLoader() - ; + ; Then restart Encore. When you do, it will give you a command you can run to install any missing dependencies. After running that command and restarting @@ -84,19 +85,20 @@ You can enable `JSX with Vue.js`_ by configuring the second parameter of the ``.enableVueLoader()`` method: .. code-block:: diff + :dedent: 0 - // webpack.config.js - // ... + // webpack.config.js + // ... - Encore - // ... - .addEntry('main', './assets/main.js') + Encore + // ... + .addEntry('main', './assets/main.js') - .enableVueLoader() + .enableVueLoader(() => {}, { + useJsx: true + }) - ; + ; Next, run or restart Encore. When you do, you will see an error message helping you install any missing dependencies. After running that command and restarting diff --git a/http_cache.rst b/http_cache.rst index ca0ccf85e9f..c64e07b181a 100644 --- a/http_cache.rst +++ b/http_cache.rst @@ -92,21 +92,22 @@ Modify the code of your front controller to wrap the default kernel into the caching kernel: .. code-block:: diff + :dedent: 0 - // public/index.php + // public/index.php + use App\CacheKernel; - use App\Kernel; + use App\Kernel; - // ... - $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); + // ... + $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); + // Wrap the default Kernel with the CacheKernel one in 'prod' environment + if ('prod' === $kernel->getEnvironment()) { + $kernel = new CacheKernel($kernel); + } - $request = Request::createFromGlobals(); - // ... + $request = Request::createFromGlobals(); + // ... The caching kernel will immediately act as a reverse proxy: caching responses from your application and returning them to the client. diff --git a/logging/channels_handlers.rst b/logging/channels_handlers.rst index 8f6e9aed98a..101c8ad57c2 100644 --- a/logging/channels_handlers.rst +++ b/logging/channels_handlers.rst @@ -189,11 +189,12 @@ For example to inject the service related to the ``app`` logger channel, change your constructor like this: .. code-block:: diff + :dedent: 0 - public function __construct(LoggerInterface $logger) + public function __construct(LoggerInterface $appLogger) - { - $this->logger = $appLogger; - } + { + $this->logger = $appLogger; + } .. _`MonologBundle`: https://github.com/symfony/monolog-bundle diff --git a/mailer.rst b/mailer.rst index ed2e0ccf041..75f5340ea91 100644 --- a/mailer.rst +++ b/mailer.rst @@ -646,16 +646,17 @@ explained in the previous sections or the ``textTemplate()`` method provided by the ``TemplatedEmail`` class: .. code-block:: diff + :dedent: 0 + use Symfony\Bridge\Twig\Mime\TemplatedEmail; - $email = (new TemplatedEmail()) - // ... + $email = (new TemplatedEmail()) + // ... - ->htmlTemplate('emails/signup.html.twig') + ->htmlTemplate('emails/signup.html.twig') + ->textTemplate('emails/signup.txt.twig') - // ... - ; + // ... + ; .. _mailer-twig-embedding-images: diff --git a/page_creation.rst b/page_creation.rst index 0d7ff3e910b..e8aea943a89 100644 --- a/page_creation.rst +++ b/page_creation.rst @@ -104,22 +104,23 @@ routes. To do this, install the annotations package: You can now add your route directly *above* the controller: .. code-block:: diff + :dedent: 0 - // src/Controller/LuckyController.php + // src/Controller/LuckyController.php - // ... + // ... + use Symfony\Component\Routing\Annotation\Route; - class LuckyController - { + class LuckyController + { + /** + * @Route("/lucky/number") + */ - public function number() - { - // this looks exactly the same - } - } + public function number() + { + // this looks exactly the same + } + } That's it! The page - http://localhost:8000/lucky/number will work exactly like before! Annotations are the recommended way to configure routes. @@ -208,17 +209,18 @@ Make sure that ``LuckyController`` extends Symfony's base :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController` class: .. code-block:: diff + :dedent: 0 - // src/Controller/LuckyController.php + // src/Controller/LuckyController.php - // ... + // ... + use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - class LuckyController + class LuckyController extends AbstractController - { - // ... - } + { + // ... + } Now, use the handy ``render()`` function to render a template. Pass it a ``number`` variable so you can use it in Twig:: diff --git a/quick_tour/flex_recipes.rst b/quick_tour/flex_recipes.rst index 435b4f07351..503b461d0e3 100644 --- a/quick_tour/flex_recipes.rst +++ b/quick_tour/flex_recipes.rst @@ -74,29 +74,30 @@ Twig: Rendering a Template Thanks to Flex, after one command, you can start using Twig immediately: .. code-block:: diff + :dedent: 0 - render('default/index.html.twig', [ - + 'name' => $name, - + ]); - } - } + - class DefaultController + + class DefaultController extends AbstractController + { + /** + * @Route("/hello/{name}") + */ + public function index($name) + { + - return new Response("Hello $name!"); + + return $this->render('default/index.html.twig', [ + + 'name' => $name, + + ]); + } + } By extending ``AbstractController``, you now have access to a number of shortcut methods and tools, like ``render()``. Create the new template: diff --git a/quick_tour/the_architecture.rst b/quick_tour/the_architecture.rst index e3b388a0bc4..e529ada972b 100644 --- a/quick_tour/the_architecture.rst +++ b/quick_tour/the_architecture.rst @@ -134,13 +134,14 @@ Yes! You can use autowiring inside a service to access *other* services. The onl difference is that it's done in the constructor: .. code-block:: diff + :dedent: 0 - logger = $logger; + } - public function getRandomGreeting() - { - // ... + public function getRandomGreeting() + { + // ... + $this->logger->info('Using the greeting: '.$greeting); - return $greeting; - } - } + return $greeting; + } + } Yes! This works too: no configuration, no time wasted. Keep coding! @@ -275,8 +276,9 @@ Oh, how do you change the environment? Change the ``APP_ENV`` environment variab from ``dev`` to ``prod``: .. code-block:: diff + :dedent: 0 - # .env + # .env - APP_ENV=dev + APP_ENV=prod @@ -317,11 +319,12 @@ your app needs a database ORM. Let's install the Doctrine ORM: Thanks to a new recipe installed by Flex, look at the ``.env`` file again: .. code-block:: diff + :dedent: 0 - ###> symfony/framework-bundle ### - APP_ENV=dev - APP_SECRET=cc86c7ca937636d5ddf1b754beb22a10 - ###< symfony/framework-bundle ### + ###> symfony/framework-bundle ### + APP_ENV=dev + APP_SECRET=cc86c7ca937636d5ddf1b754beb22a10 + ###< symfony/framework-bundle ### + ###> doctrine/doctrine-bundle ### + # ... diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 4fae7ef5991..33d9c5f26a1 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -104,33 +104,35 @@ a full HTML page. But the routing system is *much* more powerful. So let's make the route more interesting: .. code-block:: diff + :dedent: 0 - # config/routes.yaml - index: + # config/routes.yaml + index: - path: / + path: /hello/{name} - controller: 'App\Controller\DefaultController::index' + controller: 'App\Controller\DefaultController::index' The URL to this page has changed: it is *now* ``/hello/*``: the ``{name}`` acts like a wildcard that matches anything. And it gets better! Update the controller too: .. code-block:: diff + :dedent: 0 - passwordEncoder = $passwordEncoder; + } - public function load(ObjectManager $manager) - { - $user = new User(); - // ... + public function load(ObjectManager $manager) + { + $user = new User(); + // ... + $user->setPassword($this->passwordEncoder->encodePassword( + $user, + 'the_new_password' + )); - // ... - } - } + // ... + } + } You can manually encode a password by running: @@ -834,9 +835,10 @@ Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations: .. code-block:: diff + :dedent: 0 - // src/Controller/AdminController.php - // ... + // src/Controller/AdminController.php + // ... + use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; @@ -845,18 +847,18 @@ using annotations: + * + * @IsGranted("ROLE_ADMIN") + */ - class AdminController extends AbstractController - { + class AdminController extends AbstractController + { + /** + * Require ROLE_ADMIN for only this controller method. + * + * @IsGranted("ROLE_ADMIN") + */ - public function adminDashboard() - { - // ... - } - } + public function adminDashboard() + { + // ... + } + } For more information, see the `FrameworkExtraBundle documentation`_. diff --git a/security/form_login_setup.rst b/security/form_login_setup.rst index 1d269eba380..53952be1508 100644 --- a/security/form_login_setup.rst +++ b/security/form_login_setup.rst @@ -380,18 +380,19 @@ whole process works. You will *at least* need to fill in *where* you want your u be redirected after success: .. code-block:: diff + :dedent: 0 - // src/Security/LoginFormAuthenticator.php + // src/Security/LoginFormAuthenticator.php - // ... - public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) - { - // ... + // ... + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) + { + // ... - throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); + // redirect to some "app_homepage" route - of wherever you want + return new RedirectResponse($this->urlGenerator->generate('app_homepage')); - } + } Unless you have any other TODOs in that file, that's it! If you're loading users from the database, make sure you've loaded some :ref:`dummy users `. diff --git a/security/guard_authentication.rst b/security/guard_authentication.rst index 99d86c6c781..e8e64a39206 100644 --- a/security/guard_authentication.rst +++ b/security/guard_authentication.rst @@ -31,23 +31,24 @@ create your ``User`` class. Then add an ``apiToken`` property directly to your ``User`` class (the ``make:entity`` command is a good way to do this): .. code-block:: diff + :dedent: 0 - // src/Entity/User.php - namespace App\Entity; + // src/Entity/User.php + namespace App\Entity; - // ... + // ... - class User implements UserInterface - { - // ... + class User implements UserInterface + { + // ... + /** + * @ORM\Column(type="string", unique=true, nullable=true) + */ + private $apiToken; - // the getter and setter methods - } + // the getter and setter methods + } Don't forget to generate and run the migration: @@ -525,14 +526,15 @@ are two possible fixes: authenticated: .. code-block:: diff + :dedent: 0 - // src/Security/MyIpAuthenticator.php - // ... + // src/Security/MyIpAuthenticator.php + // ... + use Symfony\Component\Security\Core\Security; - class MyIpAuthenticator - { + class MyIpAuthenticator + { + private $security; + public function __construct(Security $security) @@ -540,8 +542,8 @@ are two possible fixes: + $this->security = $security; + } - public function supports(Request $request) - { + public function supports(Request $request) + { + // if there is already an authenticated user (likely due to the session) + // then return false and skip authentication: there is no need. + if ($this->security->getUser()) { @@ -550,8 +552,8 @@ are two possible fixes: + // the user is not logged in, so the authenticator should continue + return true; - } - } + } + } If you use autowiring, the ``Security`` service will automatically be passed to your authenticator. diff --git a/security/securing_services.rst b/security/securing_services.rst index 67b37dd792e..77462adad81 100644 --- a/security/securing_services.rst +++ b/security/securing_services.rst @@ -13,15 +13,16 @@ service. For example, suppose you have a ``SalesReportManager`` service and you want to include extra details only for users that have a ``ROLE_SALES_ADMIN`` role: .. code-block:: diff + :dedent: 0 - // src/Newsletter/NewsletterManager.php + // src/Newsletter/NewsletterManager.php - // ... - use Symfony\Component\Security\Core\Exception\AccessDeniedException; + // ... + use Symfony\Component\Security\Core\Exception\AccessDeniedException; + use Symfony\Component\Security\Core\Security; - class SalesReportManager - { + class SalesReportManager + { + private $security; + public function __construct(Security $security) @@ -29,19 +30,19 @@ want to include extra details only for users that have a ``ROLE_SALES_ADMIN`` ro + $this->security = $security; + } - public function sendNewsletter() - { - $salesData = []; + public function sendNewsletter() + { + $salesData = []; + if ($this->security->isGranted('ROLE_SALES_ADMIN')) { + $salesData['top_secret_numbers'] = rand(); + } - // ... - } + // ... + } - // ... - } + // ... + } If you're using the :ref:`default services.yaml configuration `, Symfony will automatically pass the ``security.helper`` to your service diff --git a/service_container.rst b/service_container.rst index 98fb5e61318..68287f11504 100644 --- a/service_container.rst +++ b/service_container.rst @@ -362,35 +362,36 @@ But there are a few cases when an argument to a service cannot be autowired. For example, suppose you want to make the admin email configurable: .. code-block:: diff + :dedent: 0 - // src/Service/SiteUpdateManager.php - // ... + // src/Service/SiteUpdateManager.php + // ... - class SiteUpdateManager - { - // ... + class SiteUpdateManager + { + // ... + private $adminEmail; - public function __construct(MessageGenerator $messageGenerator, MailerInterface $mailer) + public function __construct(MessageGenerator $messageGenerator, MailerInterface $mailer, string $adminEmail) - { - // ... + { + // ... + $this->adminEmail = $adminEmail; - } + } - public function notifyOfSiteUpdate(): bool - { - // ... + public function notifyOfSiteUpdate(): bool + { + // ... - $email = (new Email()) - // ... + $email = (new Email()) + // ... - ->to('manager@example.com') + ->to($this->adminEmail) - // ... - ; - // ... - } - } + // ... + ; + // ... + } + } If you make this change and refresh, you'll see an error: diff --git a/setup/flex.rst b/setup/flex.rst index 52708275077..df4d3442b93 100644 --- a/setup/flex.rst +++ b/setup/flex.rst @@ -57,15 +57,16 @@ manual steps: it will not be installed again: .. code-block:: diff - - { - "require": { - "symfony/flex": "^1.0", - + }, - + "conflict": { - + "symfony/symfony": "*" - } - } + :dedent: 0 + + { + "require": { + "symfony/flex": "^1.0", + + }, + + "conflict": { + + "symfony/symfony": "*" + } + } Now you must add in ``composer.json`` all the Symfony dependencies required by your project. A quick way to do that is to add all the components that diff --git a/setup/unstable_versions.rst b/setup/unstable_versions.rst index 5e11526b20e..881477c5d6a 100644 --- a/setup/unstable_versions.rst +++ b/setup/unstable_versions.rst @@ -32,15 +32,16 @@ project. Then, edit the value of all of the ``symfony/*`` libraries to the new version and change your ``minimum-stability`` to ``beta``: .. code-block:: diff + :dedent: 0 - { - "require": { + { + "require": { + "symfony/framework-bundle": "^4.0", + "symfony/finder": "^4.0", - "...": "..." - }, + "...": "..." + }, + "minimum-stability": "beta" - } + } You can also use set ``minimum-stability`` to ``dev``, or omit this line entirely, and opt into your stability on each package by using constraints diff --git a/setup/upgrade_major.rst b/setup/upgrade_major.rst index 89f80ae109f..7b0d2117376 100644 --- a/setup/upgrade_major.rst +++ b/setup/upgrade_major.rst @@ -130,41 +130,43 @@ Composer by modifying your ``composer.json`` file and changing all the libraries starting with ``symfony/`` to the new major version: .. code-block:: diff + :dedent: 0 - { - "...": "...", + { + "...": "...", - "require": { + "require": { - "symfony/cache": "4.4.*", + "symfony/cache": "5.0.*", - "symfony/config": "4.4.*", + "symfony/config": "5.0.*", - "symfony/console": "4.4.*", + "symfony/console": "5.0.*", - "...": "...", + "...": "...", - "...": "A few libraries starting with - symfony/ follow their own versioning scheme. You - do not need to update these versions: you can - upgrade them independently whenever you want", - "symfony/monolog-bundle": "^3.5", - }, - "...": "...", - } + "...": "A few libraries starting with + symfony/ follow their own versioning scheme. You + do not need to update these versions: you can + upgrade them independently whenever you want", + "symfony/monolog-bundle": "^3.5", + }, + "...": "...", + } At the bottom of your ``composer.json`` file, in the ``extra`` block you can find a data setting for the Symfony version. Make sure to also upgrade this one. For instance, update it to ``5.0.*`` to upgrade to Symfony 5.0: .. code-block:: diff + :dedent: 0 - "extra": { - "symfony": { - "allow-contrib": false, + "extra": { + "symfony": { + "allow-contrib": false, - "require": "4.4.*" + "require": "5.0.*" - } - } + } + } Next, use Composer to download new versions of the libraries: diff --git a/setup/upgrade_minor.rst b/setup/upgrade_minor.rst index 09a88124fa8..99059813559 100644 --- a/setup/upgrade_minor.rst +++ b/setup/upgrade_minor.rst @@ -27,40 +27,42 @@ probably need to update the version constraint next to each library starting ``symfony/``. Suppose you are upgrading from Symfony 4.3 to 4.4: .. code-block:: diff + :dedent: 0 - { - "...": "...", + { + "...": "...", - "require": { + "require": { - "symfony/cache": "4.3.*", + "symfony/cache": "4.4.*", - "symfony/config": "4.3.*", + "symfony/config": "4.4.*", - "symfony/console": "4.3.*", + "symfony/console": "4.4.*", - "...": "...", + "...": "...", - "...": "A few libraries starting with - symfony/ follow their versioning scheme. You - do not need to update these versions: you can - upgrade them independently whenever you want", - "symfony/monolog-bundle": "^3.5", - }, - "...": "...", - } + "...": "A few libraries starting with + symfony/ follow their versioning scheme. You + do not need to update these versions: you can + upgrade them independently whenever you want", + "symfony/monolog-bundle": "^3.5", + }, + "...": "...", + } Your ``composer.json`` file should also have an ``extra`` block that you will *also* need to update: .. code-block:: diff + :dedent: 0 - "extra": { - "symfony": { - "...": "...", + "extra": { + "symfony": { + "...": "...", - "require": "4.3.*" + "require": "4.4.*" - } - } + } + } Next, use Composer to download new versions of the libraries: