From d802d42d052e473999e24b825715d52f0b1d8e69 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 15 May 2013 20:06:43 +0200 Subject: [PATCH] updated code for Symfony 2.3 and made minor tweaks to the text --- book/part01.rst | 25 +++++++++++++------------ book/part02.rst | 17 +++++++++-------- book/part03.rst | 12 ++++++------ book/part04.rst | 13 +++---------- book/part05.rst | 12 ++++++------ book/part06.rst | 8 ++++---- book/part07.rst | 8 ++++---- book/part09.rst | 10 +++++----- book/part11.rst | 2 +- book/part12.rst | 12 ++++++------ 10 files changed, 57 insertions(+), 62 deletions(-) diff --git a/book/part01.rst b/book/part01.rst index 513cb82d243..b22945c1365 100644 --- a/book/part01.rst +++ b/book/part01.rst @@ -53,20 +53,21 @@ Symfony2 Components. based on the Symfony2 Components. The code is rather slim and it leverages many aspects of the Symfony2 Components. -Many modern web frameworks call themselves MVC frameworks. We won't talk about -MVC here as the Symfony2 Components are able to create any type of frameworks, -not just the ones that follow the MVC architecture. Anyway, if you have a look -at the MVC semantics, this book is about how to create the Controller part of -a framework. For the Model and the View, it really depends on your personal -taste and I will let you use any existing third-party libraries (Doctrine, -Propel, or plain-old PDO for the Model; PHP or Twig for the View). +Many modern web frameworks advertize themselves as being MVC frameworks. We +won't talk about the MVC pattern as the Symfony2 Components are able to create +any type of frameworks, not just the ones that follow the MVC architecture. +Anyway, if you have a look at the MVC semantics, this book is about how to +create the Controller part of a framework. For the Model and the View, it +really depends on your personal taste and I will let you use any existing +third-party libraries (Doctrine, Propel, or plain-old PDO for the Model; PHP +or Twig for the View). When creating a framework, following the MVC pattern is not the right goal. -The main goal should be the Separation of Concerns; I actually think that this -is the only design pattern that you should really care about. The fundamental -principles of the Symfony2 Components are focused on the HTTP specification. -As such, the frameworks that we are going to create should be more accurately -labelled as HTTP frameworks or Request/Response frameworks. +The main goal should be the **Separation of Concerns**; I actually think that +this is the only design pattern that you should really care about. The +fundamental principles of the Symfony2 Components are focused on the HTTP +specification. As such, the frameworks that we are going to create should be +more accurately labelled as HTTP frameworks or Request/Response frameworks. Before we start --------------- diff --git a/book/part02.rst b/book/part02.rst index c86da9deabb..226547a6ab1 100644 --- a/book/part02.rst +++ b/book/part02.rst @@ -129,7 +129,7 @@ dependency for the project: { "require": { - "symfony/http-foundation": "2.1.*" + "symfony/http-foundation": "~2.3" } } @@ -170,8 +170,8 @@ first outputs the HTTP headers followed by the content). Before the ``send()`` call, we should have added a call to the ``prepare()`` method (``$response->prepare($request);``) to ensure that our Response were compliant with the HTTP specification. For instance, if - we were to call the page with the ``HEAD`` method, it would have removed - the content of the Response. + we were to call the page with the ``HEAD`` method, it would remove the + content of the Response. The main difference with the previous code is that you have total control of the HTTP messages. You can create whatever request you want and you are in @@ -275,11 +275,12 @@ secure? The ``$_SERVER['HTTP_X_FORWARDED_FOR']`` value cannot be trusted as it can be manipulated by the end user when there is no proxy. So, if you are using this code in production without a proxy, it becomes trivially easy to abuse your system. That's not the case with the ``getClientIp()`` method as -you must explicitly trust this header by calling ``trustProxyData()``:: +you must explicitly trust your reverse proxies by calling +``setTrustedProxies()``:: getClientIp(true)) { // the client is a known one, so give it some more privilege @@ -302,9 +303,9 @@ Using just the Symfony2 HttpFoundation component already allows you to write better and more testable code. It also allows you to write code faster as many day-to-day problems have already been solved for you. -As a matter of fact, projects like Drupal have adopted (for the upcoming -version 8) the HttpFoundation component; if it works for them, it will -probably work for you. Don't reinvent the wheel. +As a matter of fact, projects like Drupal have adopted the HttpFoundation +component; if it works for them, it will probably work for you. Don't reinvent +the wheel. I've almost forgot to talk about one added benefit: using the HttpFoundation component is the start of better interoperability between all frameworks and diff --git a/book/part03.rst b/book/part03.rst index d795d57b565..4ca7ee1cc51 100644 --- a/book/part03.rst +++ b/book/part03.rst @@ -65,8 +65,8 @@ And for the "Goodbye" page:: We have indeed moved most of the shared code into a central place, but it does not feel like a good abstraction, doesn't it? First, we still have the -``send()`` method in all pages, then our pages does not look like templates, -and we are still not able to test this code properly. +``send()`` method in all pages, then our pages do not look like templates, and +we are still not able to test this code properly. Moreover, adding a new page means that we need to create a new PHP script, which name is exposed to the end user via the URL @@ -140,9 +140,9 @@ To access a page, you must now use the ``front.php`` script: able to type ``http://example.com/hello?name=Fabien``, which looks much better. -So, the trick is the usage of the ``Request::getPathInfo()`` method which -returns the path of the Request by removing the front controller script name -including its sub-directories (only if needed -- see above tip). +The trick is the usage of the ``Request::getPathInfo()`` method which returns +the path of the Request by removing the front controller script name including +its sub-directories (only if needed -- see above tip). .. tip:: @@ -205,7 +205,7 @@ And the ``hello.php`` script can now be converted to a template:: Hello -We have our framework for today:: +We have the first version of our framework:: -* Routes configuration has been moved to its own file: +* Route configuration has been moved to its own file: .. code-block:: php @@ -232,11 +232,4 @@ generate absolute URLs:: echo $dumper->dump(); - Want even more performance? Dump your routes as a set of Apache rewrite - rules:: - - $dumper = new Routing\Matcher\Dumper\ApacheMatcherDumper($routes); - - echo $dumper->dump(); - .. _`documentation`: http://symfony.com/doc/current/components/routing.html diff --git a/book/part05.rst b/book/part05.rst index a10d9a7a21a..f2494c332e7 100644 --- a/book/part05.rst +++ b/book/part05.rst @@ -33,8 +33,8 @@ As the rendering is now done by an external function (``render_template()`` here), we need to pass to it the attributes extracted from the URL. We could have passed them as an additional argument to ``render_template()``, but instead, let's use another feature of the ``Request`` class called -*attributes*: Request attributes lets you attach additional information about -the Request that is not directly related to the HTTP Request data. +*attributes*: Request attributes is a way to attach additional information +about the Request that is not directly related to the HTTP Request data. You can now create the ``render_template()`` function, a generic controller that renders a template when there is no specific logic. To keep the same @@ -177,10 +177,10 @@ framework does not need to be modified in any way, just create a new return $routes; The ``is_leap_year()`` function returns ``true`` when the given year is a leap -year, ``false`` otherwise. If the year is null, the current year is tested. -The controller is simple: it gets the year from the request attributes, pass -it to the `is_leap_year()`` function, and according to the return value it -creates a new Response object. +year, ``false`` otherwise. If the year is ``null``, the current year is +tested. The controller is simple: it gets the year from the request +attributes, pass it to the `is_leap_year()`` function, and according to the +return value it creates a new Response object. As always, you can decide to stop here and use the framework as is; it's probably all you need to create simple websites like those fancy one-page diff --git a/book/part06.rst b/book/part06.rst index 868ea17a057..d7d721c73ef 100644 --- a/book/part06.rst +++ b/book/part06.rst @@ -41,9 +41,9 @@ component:: { "require": { - "symfony/http-foundation": "2.1.*", - "symfony/routing": "2.1.*", - "symfony/http-kernel": "2.1.*" + "symfony/http-foundation": "~2.3", + "symfony/routing": "~2.3", + "symfony/http-kernel": "~2.3" } } @@ -145,7 +145,7 @@ method is not defined, an argument has no matching attribute, ...). With the great flexibility of the default controller resolver, you might wonder why someone would want to create another one (why would there be an - interface if not). Two examples: in Symfony2, ``getController()`` is + interface if not?). Two examples: in Symfony2, ``getController()`` is enhanced to support `controllers as services`_; and in `FrameworkExtraBundle`_, ``getArguments()`` is enhanced to support parameter converters, where request attributes are converted to objects diff --git a/book/part07.rst b/book/part07.rst index 76f95a3df0e..004ca4a140d 100644 --- a/book/part07.rst +++ b/book/part07.rst @@ -89,12 +89,12 @@ be autoloaded, update the ``composer.json`` file: { "require": { - "symfony/http-foundation": "2.1.*", - "symfony/routing": "2.1.*", - "symfony/http-kernel": "2.1.*" + "symfony/http-foundation": "~2.3", + "symfony/routing": "~2.3", + "symfony/http-kernel": "~2.3" }, "autoload": { - "psr-0": { "Simplex": "src/", "Calendar": "src/" } + "psr-0": { "Simplex\\": "src/", "Calendar\\": "src/" } } } diff --git a/book/part09.rst b/book/part09.rst index 53649990457..05604afce89 100644 --- a/book/part09.rst +++ b/book/part09.rst @@ -21,13 +21,13 @@ version of this pattern: { "require": { - "symfony/http-foundation": "2.1.*", - "symfony/routing": "2.1.*", - "symfony/http-kernel": "2.1.*", - "symfony/event-dispatcher": "2.1.*" + "symfony/http-foundation": "~2.3", + "symfony/routing": "~2.3", + "symfony/http-kernel": "~2.3", + "symfony/event-dispatcher": "~2.3" }, "autoload": { - "psr-0": { "Simplex": "src/", "Calendar": "src/" } + "psr-0": { "Simplex\\": "src/", "Calendar\\": "src/" } } } diff --git a/book/part11.rst b/book/part11.rst index 1e29e214fc5..0352fbf4fba 100644 --- a/book/part11.rst +++ b/book/part11.rst @@ -110,7 +110,7 @@ The error controller reads as follows:: VoilĂ ! Clean and customizable error management without efforts. And of course, if your controller throws an exception, HttpKernel will handle it nicely. -In part 2, we have talked about the ``Response::prepare()`` method, which +In chapter two, we talked about the ``Response::prepare()`` method, which ensures that a Response is compliant with the HTTP specification. It is probably a good idea to always call it just before sending the Response to the client; that's what the ``ResponseListener`` does:: diff --git a/book/part12.rst b/book/part12.rst index 0b79feae509..41330f5666c 100644 --- a/book/part12.rst +++ b/book/part12.rst @@ -95,14 +95,14 @@ container: { "require": { - "symfony/http-foundation": "2.1.*", - "symfony/routing": "2.1.*", - "symfony/http-kernel": "2.1.*", - "symfony/event-dispatcher": "2.1.*", - "symfony/dependency-injection": "2.1.*" + "symfony/http-foundation": "~2.3", + "symfony/routing": "~2.3", + "symfony/http-kernel": "~2.3", + "symfony/event-dispatcher": "~2.3", + "symfony/dependency-injection": "~2.3" }, "autoload": { - "psr-0": { "Simplex": "src/", "Calendar": "src/" } + "psr-0": { "Simplex\\": "src/", "Calendar\\": "src/" } } }