1
+ .. index ::
2
+ single: Symfony versus Flat PHP
3
+
1
4
.. _symfony2-versus-flat-php :
2
5
3
6
Symfony versus Flat PHP
4
7
=======================
5
8
6
9
**Why is Symfony better than just opening up a file and writing flat PHP? **
7
10
8
- If you've never used a PHP framework, aren't familiar with the MVC philosophy,
9
- or just wonder what all the *hype * is around Symfony, this chapter is for
10
- you. Instead of *telling * you that Symfony allows you to develop faster and
11
- better software than with flat PHP, you'll see for yourself.
11
+ If you've never used a PHP framework, aren't familiar with the
12
+ `Model-View-Controller `_ (MVC) philosophy, or just wonder what all the *hype *
13
+ is around Symfony, this chapter is for you. Instead of *telling * you that
14
+ Symfony allows you to develop faster and better software than with flat PHP,
15
+ you'll see for yourself.
12
16
13
17
In this chapter, you'll write a simple application in flat PHP, and then
14
18
refactor it to be more organized. You'll travel through time, seeing the
@@ -98,11 +102,12 @@ the code that prepares the HTML "presentation"::
98
102
require 'templates/list.php';
99
103
100
104
101
- The HTML code is now stored in a separate file ( ``templates/list.php ``) , which
105
+ The HTML code is now stored in a separate file ``templates/list.php ``, which
102
106
is primarily an HTML file that uses a template-like PHP syntax:
103
107
104
108
.. code-block :: html+php
105
109
110
+ <!-- templates/list.php -->
106
111
<!DOCTYPE html>
107
112
<html>
108
113
<head>
@@ -179,6 +184,7 @@ of the application are isolated in a new file called ``model.php``::
179
184
180
185
The controller (``index.php ``) is now very simple::
181
186
187
+ // index.php
182
188
require_once 'model.php';
183
189
184
190
$posts = get_all_posts();
@@ -197,7 +203,7 @@ offering various advantages and the opportunity to reuse almost everything
197
203
on different pages.
198
204
199
205
The only part of the code that *can't * be reused is the page layout. Fix
200
- that by creating a new ``layout.php `` file:
206
+ that by creating a new ``templates/ layout.php `` file:
201
207
202
208
.. code-block :: html+php
203
209
@@ -212,11 +218,12 @@ that by creating a new ``layout.php`` file:
212
218
</body>
213
219
</html>
214
220
215
- The template ( ``templates/list.php ``) can now be simplified to "extend"
216
- the layout:
221
+ The template ``templates/list.php `` can now be simplified to "extend"
222
+ the `` templates/ layout.php `` :
217
223
218
224
.. code-block :: html+php
219
225
226
+ <!-- templates/list.php -->
220
227
<?php $title = 'List of Posts' ?>
221
228
222
229
<?php ob_start() ?>
@@ -237,8 +244,9 @@ the layout:
237
244
You now have a setup that will allow you to reuse the layout.
238
245
Unfortunately, to accomplish this, you're forced to use a few ugly
239
246
PHP functions (``ob_start() ``, ``ob_get_clean() ``) in the template. Symfony
240
- uses a Templating component that allows this to be accomplished cleanly
241
- and easily. You'll see it in action shortly.
247
+ uses a :doc: `Templating </components/templating/introduction >` component
248
+ that allows this to be accomplished cleanly and easily. You'll see it in
249
+ action shortly.
242
250
243
251
Adding a Blog "show" Page
244
252
-------------------------
@@ -270,6 +278,7 @@ an individual blog result based on a given id::
270
278
Next, create a new file called ``show.php `` - the controller for this new
271
279
page::
272
280
281
+ // show.php
273
282
require_once 'model.php';
274
283
275
284
$post = get_post_by_id($_GET['id']);
@@ -281,6 +290,7 @@ the individual blog post:
281
290
282
291
.. code-block :: html+php
283
292
293
+ <!-- templates/show.php -->
284
294
<?php $title = $post['title'] ?>
285
295
286
296
<?php ob_start() ?>
@@ -327,9 +337,9 @@ application change slightly, but start to become more flexible:
327
337
/index.php/show => Blog post show page (index.php executed)
328
338
329
339
.. tip ::
330
- The `` index.php `` portion of the URI can be removed if using Apache
331
- rewrite rules (or equivalent). In that case, the resulting URI of the
332
- blog show page would be simply ``/show ``.
340
+
341
+ By using rewrite rules in your :doc: ` web server configuration < /cookbook/configuration/web_server_configuration >`,
342
+ the `` index.php `` won't be needed and you will have beautiful, clean URLs (e.g. ``/show ``) .
333
343
334
344
When using a front controller, a single PHP file (``index.php `` in this case)
335
345
renders *every * request. For the blog post show page, ``/index.php/show `` will
@@ -364,8 +374,9 @@ on the requested URI::
364
374
}
365
375
366
376
For organization, both controllers (formerly ``index.php `` and ``show.php ``)
367
- are now PHP functions and each has been moved into a separate file, ``controllers.php ``::
377
+ are now PHP functions and each has been moved into a separate file named ``controllers.php ``::
368
378
379
+ // controllers.php
369
380
function list_action()
370
381
{
371
382
$posts = get_all_posts();
@@ -382,7 +393,11 @@ As a front controller, ``index.php`` has taken on an entirely new role, one
382
393
that includes loading the core libraries and routing the application so that
383
394
one of the two controllers (the ``list_action() `` and ``show_action() ``
384
395
functions) is called. In reality, the front controller is beginning to look and
385
- act a lot like Symfony's mechanism for handling and routing requests.
396
+ act a lot like how Symfony handles and routes requests.
397
+
398
+ But but careful not to confuse the terms *front controller * and *controller *. Your
399
+ app will usually have just *one * front controller, which boots your code. You will
400
+ have *many * controller functions: one for each page.
386
401
387
402
.. tip ::
388
403
@@ -393,8 +408,8 @@ act a lot like Symfony's mechanism for handling and routing requests.
393
408
394
409
By now, the application has evolved from a single PHP file into a structure
395
410
that is organized and allows for code reuse. You should be happier, but far
396
- from satisfied. For example, the " routing" system is fickle, and wouldn't
397
- recognize that the list page ( ``/index.php ``) should be accessible also via ``/ ``
411
+ from satisfied. For example, the routing system is fickle, and wouldn't
412
+ recognize that the list page - ``/index.php `` - should be accessible also via ``/ ``
398
413
(if Apache rewrite rules were added). Also, instead of developing the blog,
399
414
a lot of time is being spent working on the "architecture" of the code (e.g.
400
415
routing, calling controllers, templates, etc.). More time will need to be
@@ -407,7 +422,7 @@ Add a Touch of Symfony
407
422
~~~~~~~~~~~~~~~~~~~~~~
408
423
409
424
Symfony to the rescue. Before actually using Symfony, you need to download
410
- it. This can be done by using Composer, which takes care of downloading the
425
+ it. This can be done by using ` Composer `_ , which takes care of downloading the
411
426
correct version and all its dependencies and provides an autoloader. An
412
427
autoloader is a tool that makes it possible to start using PHP classes
413
428
without explicitly including the file containing the class.
@@ -427,7 +442,7 @@ content:
427
442
}
428
443
429
444
Next, `download Composer `_ and then run the following command, which will download Symfony
430
- into a vendor/ directory:
445
+ into a `` vendor/ `` directory:
431
446
432
447
.. code-block :: bash
433
448
@@ -501,7 +516,8 @@ incidentally, acts quite a bit like the Symfony templating engine::
501
516
502
517
By bringing in a small part of Symfony, the application is more flexible and
503
518
reliable. The ``Request `` provides a dependable way to access information
504
- about the HTTP request. Specifically, the ``getPathInfo() `` method returns
519
+ about the HTTP request. Specifically, the
520
+ :method: `Symfony\\ Component\\ HttpFoundation\\ Request::getPathInfo ` method returns
505
521
a cleaned URI (always returning ``/show `` and never ``/index.php/show ``).
506
522
So, even if the user goes to ``/index.php/show ``, the application is intelligent
507
523
enough to route the request through ``show_action() ``.
@@ -520,8 +536,10 @@ The blog has come a *long* way, but it still contains a lot of code for such
520
536
a simple application. Along the way, you've made a simple routing
521
537
system and a method using ``ob_start() `` and ``ob_get_clean() `` to render
522
538
templates. If, for some reason, you needed to continue building this "framework"
523
- from scratch, you could at least use Symfony's standalone `Routing `_ and
524
- `Templating `_ components, which already solve these problems.
539
+ from scratch, you could at least use Symfony's standalone
540
+ :doc: `Routing </components/routing/introduction >` and
541
+ :doc: `Templating </components/templating/introduction >` components, which already
542
+ solve these problems.
525
543
526
544
Instead of re-solving common problems, you can let Symfony take care of
527
545
them for you. Here's the same sample application, now built in Symfony::
@@ -559,10 +577,14 @@ them for you. Here's the same sample application, now built in Symfony::
559
577
}
560
578
}
561
579
562
- The two controllers are still lightweight. Each uses the
580
+ Notice, both controller functions now live inside a "controller class". This is a
581
+ nice way to group related pages. The controller functions are also sometimes called
582
+ *actions *.
583
+
584
+ The two controllers (or actions) are still lightweight. Each uses the
563
585
:doc: `Doctrine ORM library </book/doctrine >` to retrieve objects from the
564
586
database and the Templating component to render a template and return a
565
- ``Response `` object. The list template is now quite a bit simpler:
587
+ ``Response `` object. The list `` list.php `` template is now quite a bit simpler:
566
588
567
589
.. code-block :: html+php
568
590
@@ -585,7 +607,7 @@ database and the Templating component to render a template and return a
585
607
<?php endforeach ?>
586
608
</ul>
587
609
588
- The layout is nearly identical:
610
+ The `` layout.php `` file is nearly identical:
589
611
590
612
.. code-block :: html+php
591
613
@@ -605,12 +627,13 @@ The layout is nearly identical:
605
627
606
628
.. note ::
607
629
608
- The show template is left as an exercise, as it should be trivial to
609
- create based on the list template.
630
+ The show `` show.php `` template is left as an exercise: updating it should be
631
+ really similar to updating the `` list.php `` template.
610
632
611
- When Symfony's engine (called the `` Kernel `` ) boots up, it needs a map so
633
+ When Symfony's engine (called the Kernel) boots up, it needs a map so
612
634
that it knows which controllers to execute based on the request information.
613
- A routing configuration map provides this information in a readable format:
635
+ A routing configuration map - ``app/config/routing.yml `` - provides this information
636
+ in a readable format:
614
637
615
638
.. code-block :: yaml
616
639
@@ -624,9 +647,8 @@ A routing configuration map provides this information in a readable format:
624
647
defaults : { _controller: AppBundle:Blog:show }
625
648
626
649
Now that Symfony is handling all the mundane tasks, the front controller
627
- is dead simple. And since it does so little, you'll never have to touch
628
- it once it's created (and if you use a `Symfony distribution `_, you won't
629
- even need to create it!)::
650
+ ``web/app.php `` is dead simple. And since it does so little, you'll never
651
+ have to touch it::
630
652
631
653
// web/app.php
632
654
require_once __DIR__.'/../app/bootstrap.php';
@@ -637,55 +659,29 @@ even need to create it!)::
637
659
$kernel = new AppKernel('prod', false);
638
660
$kernel->handle(Request::createFromGlobals())->send();
639
661
640
- The front controller's only job is to initialize Symfony's engine (``Kernel ``)
641
- and pass it a ``Request `` object to handle. Symfony's core then uses the
642
- routing map to determine which controller to call. Just like before, the
643
- controller method is responsible for returning the final ``Response `` object.
644
- There's really not much else to it.
645
-
646
- For a visual representation of how Symfony handles each request, see the
647
- :ref: `request flow diagram <request-flow-figure >`.
648
-
649
- .. _where-symfony2-delivers :
662
+ The front controller's only job is to initialize Symfony's engine (called the
663
+ Kernel) and pass it a ``Request `` object to handle. The Symfony core
664
+ asks the router to inspect the request. The router matches the incoming URL
665
+ to a specific route and returns information about the route, including the
666
+ controller that should be executed. The correct controller from the matched
667
+ route is executed and your code inside the controller creates and returns the
668
+ appropriate ``Response `` object. The HTTP headers and content of the ``Response ``
669
+ object are sent back to the client.
650
670
651
- Where Symfony Delivers
652
- ~~~~~~~~~~~~~~~~~~~~~~
653
-
654
- In the upcoming chapters, you'll learn more about how each piece of Symfony
655
- works and the recommended organization of a project. For now, have a look
656
- at how migrating the blog from flat PHP to Symfony has improved life:
671
+ It's a beautiful thing.
657
672
658
- * Your application now has **clear and consistently organized code ** (though
659
- Symfony doesn't force you into this). This promotes **reusability ** and
660
- allows for new developers to be productive in your project more quickly;
661
-
662
- * 100% of the code you write is for *your * application. You **don't need
663
- to develop or maintain low-level utilities ** such as autoloading,
664
- :doc: `routing </book/routing >`, or rendering :doc: `controllers </book/controller >`;
665
-
666
- * Symfony gives you **access to open source tools ** such as Doctrine and the
667
- Templating, Security, Form, Validation and Translation components (to name
668
- a few);
669
-
670
- * The application now enjoys **fully-flexible URLs ** thanks to the Routing
671
- component;
672
-
673
- * Symfony's HTTP-centric architecture gives you access to powerful tools
674
- such as **HTTP caching ** powered by **Symfony's internal HTTP cache ** or
675
- more powerful tools such as `Varnish `_. This is covered in a later chapter
676
- all about :doc: `caching </book/http_cache >`.
677
-
678
- And perhaps best of all, by using Symfony, you now have access to a whole
679
- set of **high-quality open source tools developed by the Symfony community **!
680
- A good selection of Symfony community tools can be found on `KnpBundles.com `_.
673
+ .. figure :: /images/request-flow.png
674
+ :align: center
675
+ :alt: Symfony request flow
681
676
682
677
Better Templates
683
- ----------------
678
+ ~~~~~~~~~~~~~~~~
684
679
685
680
If you choose to use it, Symfony comes standard with a templating engine
686
681
called `Twig `_ that makes templates faster to write and easier to read.
687
682
It means that the sample application could contain even less code! Take,
688
- for example, the list template written in Twig:
683
+ for example, rewriting ``list.html.php `` template in Twig would look like
684
+ this:
689
685
690
686
.. code-block :: html+twig
691
687
@@ -707,7 +703,7 @@ for example, the list template written in Twig:
707
703
</ul>
708
704
{% endblock %}
709
705
710
- The corresponding ``layout.html.twig `` template is also easier to write :
706
+ And rewriting ``layout.html.php `` template in Twig would look like this :
711
707
712
708
.. code-block :: html+twig
713
709
@@ -726,18 +722,52 @@ Twig is well-supported in Symfony. And while PHP templates will always
726
722
be supported in Symfony, the many advantages of Twig will continue to
727
723
be discussed. For more information, see the :doc: `templating chapter </book/templating >`.
728
724
725
+ Where Symfony Delivers
726
+ ----------------------
727
+
728
+ In the upcoming chapters, you'll learn more about how each piece of Symfony
729
+ works and how you can organize your project. For now, celebrate at how migrating
730
+ the blog from flat PHP to Symfony has improved life:
731
+
732
+ * Your application now has **clear and consistently organized code ** (though
733
+ Symfony doesn't force you into this). This promotes **reusability ** and
734
+ allows for new developers to be productive in your project more quickly;
735
+
736
+ * 100% of the code you write is for *your * application. You **don't need
737
+ to develop or maintain low-level utilities ** such as autoloading,
738
+ :doc: `routing </book/routing >`, or rendering :doc: `controllers </book/controller >`;
739
+
740
+ * Symfony gives you **access to open source tools ** such as `Doctrine `_ and the
741
+ :doc: `Templating </components/templating/introduction >`,
742
+ :doc: `Security </components/security/introduction >`,
743
+ :doc: `Form </components/form/introduction >`, `Validator `_ and
744
+ :doc: `Translation </components/translation/introduction >` components (to name
745
+ a few);
746
+
747
+ * The application now enjoys **fully-flexible URLs ** thanks to the Routing
748
+ component;
749
+
750
+ * Symfony's HTTP-centric architecture gives you access to powerful tools
751
+ such as **HTTP caching ** powered by **Symfony's internal HTTP cache ** or
752
+ more powerful tools such as `Varnish `_. This is covered in a later chapter
753
+ all about :doc: `caching </book/http_cache >`.
754
+
755
+ And perhaps best of all, by using Symfony, you now have access to a whole
756
+ set of **high-quality open source tools developed by the Symfony community **!
757
+ A good selection of Symfony community tools can be found on `KnpBundles.com `_.
758
+
729
759
Learn more from the Cookbook
730
760
----------------------------
731
761
732
762
* :doc: `/cookbook/templating/PHP `
733
763
* :doc: `/cookbook/controller/service `
734
764
765
+ .. _`Model-View-Controller` : https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
735
766
.. _`Doctrine` : http://www.doctrine-project.org
767
+ .. _`SQL injection attack` : https://en.wikipedia.org/wiki/SQL_injection
768
+ .. _`Composer` : https://getcomposer.org
736
769
.. _`download Composer` : https://getcomposer.org/download/
737
- .. _`Routing` : https://github.com/symfony/routing
738
- .. _`Templating` : https://github.com/symfony/templating
739
- .. _`KnpBundles.com` : http://knpbundles.com/
740
- .. _`Twig` : http://twig.sensiolabs.org
770
+ .. _`Validator` : https://github.com/symfony/validator
741
771
.. _`Varnish` : https://www.varnish-cache.org/
742
- .. _`PHPUnit ` : http://www.phpunit.de
743
- .. _`Symfony distribution ` : https ://github.com/symfony/symfony-standard
772
+ .. _`KnpBundles.com ` : http://knpbundles.com/
773
+ .. _`Twig ` : http ://twig.sensiolabs.org
0 commit comments