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
@@ -103,6 +107,7 @@ 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
@@ -217,6 +223,7 @@ the layout:
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
-------------------------
@@ -248,7 +256,7 @@ and reusable. To prove it, add a blog "show" page, which displays an individual
248
256
blog post identified by an ``id `` query parameter.
249
257
250
258
To begin, create a new function in the ``model.php `` file that retrieves
251
- an individual blog result based on a given id ::
259
+ an individual blog result based on a given `` id `` ::
252
260
253
261
// model.php
254
262
function get_post_by_id($id)
@@ -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,10 @@ 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
+ Using Apache's ``mod_rewrite `` (or equivalent with other web servers),
342
+ the URL can easily be cleaned up - ``index.php `` portion removed -
343
+ to be just ``/show ``.
333
344
334
345
When using a front controller, a single PHP file (``index.php `` in this case)
335
346
renders *every * request. For the blog post show page, ``/index.php/show `` will
@@ -364,8 +375,12 @@ on the requested URI::
364
375
}
365
376
366
377
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 ``::
378
+ are now PHP functions and each has been moved into a separate file named
379
+ ``controllers.php ``. The job of each PHP function, now called a
380
+ :term: `controller `, is to use information from the ``Request `` object to create
381
+ and return a ``Response `` object.::
368
382
383
+ // controllers.php
369
384
function list_action()
370
385
{
371
386
$posts = get_all_posts();
@@ -384,6 +399,14 @@ one of the two controllers (the ``list_action()`` and ``show_action()``
384
399
functions) is called. In reality, the front controller is beginning to look and
385
400
act a lot like Symfony's mechanism for handling and routing requests.
386
401
402
+ .. note ::
403
+
404
+ Though similarly named, a "front controller" is different from the PHP functions
405
+ called "controllers" talked about in this chapter. A front controller is a short PHP
406
+ file through which all requests are directed. "Controller" functions are grouped in
407
+ several files and they hold your code which creates and returns the appropriate
408
+ ``Response `` object. Controllers are also called *actions *.
409
+
387
410
.. tip ::
388
411
389
412
Another advantage of a front controller is flexible URLs. Notice that
@@ -393,21 +416,19 @@ act a lot like Symfony's mechanism for handling and routing requests.
393
416
394
417
By now, the application has evolved from a single PHP file into a structure
395
418
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
419
+ from satisfied. For example, the routing system is fickle, and wouldn't
397
420
recognize that the list page (``/index.php ``) should be accessible also via ``/ ``
398
421
(if Apache rewrite rules were added). Also, instead of developing the blog,
399
422
a lot of time is being spent working on the "architecture" of the code (e.g.
400
423
routing, calling controllers, templates, etc.). More time will need to be
401
424
spent to handle form submissions, input validation, logging and security.
402
425
Why should you have to reinvent solutions to all these routine problems?
403
426
404
- .. _add-a-touch-of-symfony2 :
405
-
406
427
Add a Touch of Symfony
407
428
~~~~~~~~~~~~~~~~~~~~~~
408
429
409
430
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
431
+ it. This can be done by using ` Composer `_ , which takes care of downloading the
411
432
correct version and all its dependencies and provides an autoloader. An
412
433
autoloader is a tool that makes it possible to start using PHP classes
413
434
without explicitly including the file containing the class.
@@ -427,7 +448,7 @@ content:
427
448
}
428
449
429
450
Next, `download Composer `_ and then run the following command, which will download Symfony
430
- into a vendor/ directory:
451
+ into a `` vendor/ `` directory:
431
452
432
453
.. code-block :: bash
433
454
@@ -511,17 +532,17 @@ allowing HTTP headers and content to be added via an object-oriented interface.
511
532
And while the responses in this application are simple, this flexibility
512
533
will pay dividends as your application grows.
513
534
514
- .. _the-sample-application-in-symfony2 :
515
-
516
535
The Sample Application in Symfony
517
536
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518
537
519
538
The blog has come a *long * way, but it still contains a lot of code for such
520
539
a simple application. Along the way, you've made a simple routing
521
540
system and a method using ``ob_start() `` and ``ob_get_clean() `` to render
522
541
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.
542
+ from scratch, you could at least use Symfony's standalone
543
+ :doc: `Routing </components/routing/introduction >` and
544
+ :doc: `Templating </components/templating/introduction >` components, which already
545
+ solve these problems.
525
546
526
547
Instead of re-solving common problems, you can let Symfony take care of
527
548
them for you. Here's the same sample application, now built in Symfony::
@@ -559,10 +580,15 @@ them for you. Here's the same sample application, now built in Symfony::
559
580
}
560
581
}
561
582
583
+ First we have a "controller class" which is a convenient way to group several
584
+ "controllers" together. So methods inside a controller class are controllers
585
+ also called *actions *. They hold code which creates and returns the appropriate
586
+ ``Response `` object.
587
+
562
588
The two controllers are still lightweight. Each uses the
563
589
:doc: `Doctrine ORM library </book/doctrine >` to retrieve objects from the
564
590
database and the Templating component to render a template and return a
565
- ``Response `` object. The list template is now quite a bit simpler:
591
+ ``Response `` object. The list (`` list.php ``) template is now quite a bit simpler:
566
592
567
593
.. code-block :: html+php
568
594
@@ -585,7 +611,7 @@ database and the Templating component to render a template and return a
585
611
<?php endforeach ?>
586
612
</ul>
587
613
588
- The layout is nearly identical:
614
+ The layout (`` layout.php ``) is nearly identical:
589
615
590
616
.. code-block :: html+php
591
617
@@ -605,12 +631,13 @@ The layout is nearly identical:
605
631
606
632
.. note ::
607
633
608
- The show template is left as an exercise, as it should be trivial to
609
- create based on the list template.
634
+ The show (`` show.php ``) template is left as an exercise, as it should be trivial to
635
+ create based on the list (`` list.php ``) template.
610
636
611
- When Symfony's engine (called the `` Kernel ` `) boots up, it needs a map so
637
+ When Symfony's engine (called the :term: ` Kernel `) boots up, it needs a map so
612
638
that it knows which controllers to execute based on the request information.
613
- A routing configuration map provides this information in a readable format:
639
+ A routing configuration map ``app/config/routing.yml `` provides this information
640
+ in a readable format:
614
641
615
642
.. code-block :: yaml
616
643
@@ -624,9 +651,9 @@ A routing configuration map provides this information in a readable format:
624
651
defaults : { _controller: AppBundle:Blog:show }
625
652
626
653
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!)::
654
+ `` web/app.php `` is dead simple. And since it does so little, you'll never
655
+ have to touch it once it's created (and if you use a `Symfony distribution `_,
656
+ you won't even need to create it!)::
630
657
631
658
// web/app.php
632
659
require_once __DIR__.'/../app/bootstrap.php';
@@ -637,16 +664,18 @@ even need to create it!)::
637
664
$kernel = new AppKernel('prod', false);
638
665
$kernel->handle(Request::createFromGlobals())->send();
639
666
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.
667
+ Front controller's only job is to initialize Symfony's engine (called the
668
+ :term: `Kernel `) and pass it a ``Request `` object to handle. The Symfony core
669
+ asks the router to inspect the request. The router matches the incoming URL
670
+ to a specific route and returns information about the route, including the
671
+ controller that should be executed. The correct controller from the matched
672
+ route is executed and the code inside the controller creates and returns the
673
+ appropriate ``Response `` object. The HTTP headers and content of the ``Response ``
674
+ object are sent back to the client.
645
675
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 :
676
+ .. figure :: /images/request-flow.png
677
+ :align: center
678
+ :alt: Symfony request flow
650
679
651
680
Where Symfony Delivers
652
681
~~~~~~~~~~~~~~~~~~~~~~
@@ -663,8 +692,11 @@ at how migrating the blog from flat PHP to Symfony has improved life:
663
692
to develop or maintain low-level utilities ** such as autoloading,
664
693
:doc: `routing </book/routing >`, or rendering :doc: `controllers </book/controller >`;
665
694
666
- * Symfony gives you **access to open source tools ** such as Doctrine and the
667
- Templating, Security, Form, Validation and Translation components (to name
695
+ * Symfony gives you **access to open source tools ** such as `Doctrine `_ and the
696
+ :doc: `Templating </components/templating/introduction >`,
697
+ :doc: `Security </components/security/introduction >`,
698
+ :doc: `Form </components/form/introduction >`, `Validator `_ and
699
+ :doc: `Translation </components/translation/introduction >` components (to name
668
700
a few);
669
701
670
702
* The application now enjoys **fully-flexible URLs ** thanks to the Routing
@@ -685,7 +717,7 @@ Better Templates
685
717
If you choose to use it, Symfony comes standard with a templating engine
686
718
called `Twig `_ that makes templates faster to write and easier to read.
687
719
It means that the sample application could contain even less code! Take,
688
- for example, the list template written in Twig:
720
+ for example, lets rewrite `` layout.html.php `` template in Twig:
689
721
690
722
.. code-block :: html+twig
691
723
@@ -707,7 +739,7 @@ for example, the list template written in Twig:
707
739
</ul>
708
740
{% endblock %}
709
741
710
- The corresponding ``layout.html.twig `` template is also easier to write:
742
+ The corresponding ``layout.html.php `` template is also easier to write in Twig :
711
743
712
744
.. code-block :: html+twig
713
745
@@ -732,12 +764,14 @@ Learn more from the Cookbook
732
764
* :doc: `/cookbook/templating/PHP `
733
765
* :doc: `/cookbook/controller/service `
734
766
767
+
768
+ .. _`MVC` : https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
735
769
.. _`Doctrine` : http://www.doctrine-project.org
770
+ .. _`SQL injection attack` : https://en.wikipedia.org/wiki/SQL_injection
771
+ .. _`Composer` : https://getcomposer.org
736
772
.. _`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
741
- .. _`Varnish` : https://www.varnish-cache.org/
742
- .. _`PHPUnit` : http://www.phpunit.de
743
773
.. _`Symfony distribution` : https://github.com/symfony/symfony-standard
774
+ .. _`Validator` : https://github.com/symfony/validator
775
+ .. _`Varnish` : https://www.varnish-cache.org/
776
+ .. _`KnpBundles.com` : http://knpbundles.com/
777
+ .. _`Twig` : http://twig.sensiolabs.org
0 commit comments