@@ -19,7 +19,7 @@ Want a logging system? No problem:
1919 $ composer require logger
2020
2121 This installs and configures (via a recipe) the powerful `Monolog `_ library. To
22- use the logger in a controller, add a new argument type-hinted with ``LoggerInterface ``:
22+ use the logger in a controller, add a new argument type-hinted with ``LoggerInterface ``::
2323
2424 use Psr\Log\LoggerInterface;
2525 // ...
@@ -71,7 +71,7 @@ Creating Services
7171
7272To keep your code organized, you can even create your own services! Suppose you
7373want to generate a random greeting (e.g. "Hello", "Yo", etc). Instead of putting
74- this code directly in your controller, create a new class:
74+ this code directly in your controller, create a new class::
7575
7676 // src/GreetingGenerator.php
7777 namespace App;
@@ -129,11 +129,189 @@ difference is that it's done in the constructor:
129129 }
130130 }
131131
132- Yes! This works too: no configuration, no time wasted.
132+ Yes! This works too: no configuration, no time wasted. Keep coding!
133133
134- Event Subscriber
135- ----------------
134+ Twig Extension & Autoconfiguration
135+ ----------------------------------
136136
137+ Thanks to Symfony's service handling, you can *extend * Symfony in many ways, like
138+ by creating an event subscriber or or a security voter for complex authorization
139+ rules. Let's add a new filter to Twig called ``greet ``. How? Just create a class
140+ that extends ``AbstractExtension ``::
137141
142+ // src/Twig/GreetExtension.php
143+ namespace App\Twig;
144+
145+ use App\GreetingGenerator;
146+ use Twig\Extension\AbstractExtension;
147+ use Twig\TwigFilter;
148+
149+ class GreetExtension extends AbstractExtension
150+ {
151+ private $greetingGenerator;
152+
153+ public function __construct(GreetingGenerator $greetingGenerator)
154+ {
155+ $this->greetingGenerator = $greetingGenerator;
156+ }
157+
158+ public function getFilters()
159+ {
160+ return [
161+ new TwigFilter('greet', [$this, 'greetUser']),
162+ ];
163+ }
164+
165+ public function greetUser($name)
166+ {
167+ $greeting = $this->greetingGenerator->getRandomGreeting();
168+
169+ return "$greeting $name!";
170+ }
171+ }
172+
173+ After creating just *one * file, you can use this immediately:
174+
175+ .. code-block :: twig
176+
177+ {# Will print something like "Hey Symfony!" #}
178+ <h1>{{ name|greet }}</h1>
179+
180+ How does this work? Symfony notices that your class extends ``AbstractExtension ``
181+ and so *automatically * registers it as a Twig extension. This is called autoconfiguration,
182+ and it works for *many * many things. Just create a class and then extend a base class
183+ (or implement an interface). Symfony takes care of the rest.
184+
185+ Blazing Speed: The Cached Container
186+ -----------------------------------
187+
188+ After seeing how much Symfony handles automatically, you might be wondering: "Doesn't
189+ this hurt performance?" Actually, no! Symfony is blazing fast.
190+
191+ How is that possible? The service system is managed by a very important object called
192+ the "container". Most frameworks have a container, but Symfony's is unique because
193+ it's *cached *. When you loaded your first page, all of the service information was
194+ compiled and saved. This means that the autowiring and autoconfiguration features
195+ add *no * overhead! It also means that you get *great * errors: Symfony inspects and
196+ validates *everything * when the container is built.
197+
198+ Now you might be wondering what happens when you update a file and the cache needs
199+ to rebuild? I like you're thinking! It's smart enough to rebuild on the next page
200+ load. But that's really the topic of the next section.
201+
202+ Development Versus Production: Environments
203+ -------------------------------------------
204+
205+ One of a framework's main jobs is to make debugging easy! And our app is *full * of
206+ great tools for this: the web debug toolbar displays at the bottom of the page, errors
207+ are big, beautiful & explicit, and any configuration cache is automatically rebuilt
208+ whenever needed.
209+
210+ But what about when you deploy to production? We will need to hide those tool and
211+ optimize for speed!
212+
213+ This is solved by Symfony's *environment * system and there are three: ``dev ``, ``prod ``
214+ and ``test ``. Based on the environment, Symfony loads different files in the ``config/ ``
215+ directory:
216+
217+ .. code-block :: text
218+
219+ config/
220+ ├─ services.yaml
221+ ├─ ...
222+ └─ packages/
223+ ├─ framework.yaml
224+ ├─ ...
225+ ├─ **dev/**
226+ ├─ monolog.yaml
227+ └─ ...
228+ ├─ **prod/**
229+ └─ monolog.yaml
230+ └─ **test/**
231+ ├─ framework.yaml
232+ └─ ...
233+ └─ routes/
234+ ├─ annotations.yaml
235+ └─ **dev/**
236+ ├─ twig.yaml
237+ └─ web_profiler.yaml
238+
239+ This is a *powerful * idea: by changing one piece of configuration (the environment),
240+ your app is transformed from a debugging-friendly experience to one that's optimized
241+ for speed.
242+
243+ Oh, how do you change the environment? Change the ``APP_ENV `` environment variable
244+ from ``dev `` to ``prod ``:
245+
246+ .. code-block :: diff
247+
248+ # .env
249+ - APP_ENV=dev
250+ + APP_ENV=prod
251+
252+ But I want to talk more about environment variables next. Change the value back
253+ to ``dev ``: debugging tools are great when you're working locally.
254+
255+ Environment Variables
256+ ---------------------
257+
258+ Every app contains configuration that's different on each server - like database
259+ connection information or passwords. How should these be stored? In files? Or some
260+ other way?
261+
262+ Symfony follows the industry best practice by storing server-based configuration
263+ as *environment * variables. This means that Symfony works *perfectly * with
264+ Platform as a Service (PaaS) deployment systems as well as Docker.
265+
266+ But setting environment variables while developing can be a pain. That's why your
267+ app automatically loads a ``.env `` file, if the ``APP_ENV `` environment variable
268+ isn't set in the environment. The keys in this file then become environment variables
269+ are and read by your app:
270+
271+ .. code-block :: bash
272+
273+ # .env
274+ # ##> symfony/framework-bundle ###
275+ APP_ENV=dev
276+ APP_SECRET=cc86c7ca937636d5ddf1b754beb22a10
277+ # ##< symfony/framework-bundle ###
278+
279+ At first, the file doesn't contain much. But as your app grows, you'll add more
280+ configuration as you need it. But, actually, it gets much more interesting! Suppose
281+ your app needs database ORM. Let's install the Doctrine ORM:
282+
283+ .. code-block :: terminal
284+
285+ $ composer require doctrine
286+
287+ Thanks to a new recipe installed by Flex, look at the ``.env `` file again:
288+
289+ .. code-block :: diff
290+
291+ ###> symfony/framework-bundle ###
292+ APP_ENV=dev
293+ APP_SECRET=cc86c7ca937636d5ddf1b754beb22a10
294+ ###< symfony/framework-bundle ###
295+
296+ + ###> doctrine/doctrine-bundle ###
297+ + # ...
298+ + DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
299+ + ###< doctrine/doctrine-bundle ###
300+
301+ The new ``DATBASE_URL `` environment variable was added *automatically * and is already
302+ referenced by the new ``doctrine.yaml `` configuration file. By combining environment
303+ variables and Flex, you're using industry best practices without any extra effort.
304+
305+ Keep Going!
306+ -----------
307+
308+ Call me crazy, but after reading this part, you should be comfortable with the most
309+ *important * parts of Symfony. Everything in Symfony is designed to get out of your
310+ way so you can keep coding and adding features, all with the speed and quality you
311+ demand.
312+
313+ That's all for the quick tour. From authentication, to forms, to caching, there is
314+ so much more to discover. Ready to dig into these topics now? Look no further - go
315+ to the official :doc: `/index ` and pick any guide you want.
138316
139317.. _`Monolog` : https://github.com/Seldaek/monolog
0 commit comments