Skip to content

Commit db9fa43

Browse files
committed
Made a lot of improvements suggested by reviewers
1 parent 126bcef commit db9fa43

12 files changed

+62
-173
lines changed

create_framework/01-introduction.rst

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
Introduction
22
============
33

4-
`Symfony2`_ is a reusable set of standalone, decoupled, and cohesive PHP
4+
`Symfony`_ is a reusable set of standalone, decoupled and cohesive PHP
55
components that solve common web development problems.
66

77
Instead of using these low-level components, you can use the ready-to-be-used
8-
Symfony2 full-stack web framework, which is based on these components... or
9-
you can create your very own framework. This book is about the latter.
8+
Symfony full-stack web framework, which is based on these components... or
9+
you can create your very own framework. This tutorial is about the latter.
1010

11-
Why would you like to create your own framework?
11+
Why would you Like to Create your Own Framework?
1212
------------------------------------------------
1313

1414
Why would you like to create your own framework in the first place? If you
@@ -18,7 +18,7 @@ creating your own altogether. Most of the time, they are right but there are
1818
a few good reasons to start creating your own framework:
1919

2020
* To learn more about the low level architecture of modern web frameworks in
21-
general and about the Symfony2 full-stack framework internals in particular;
21+
general and about the Symfony full-stack framework internals in particular;
2222

2323
* To create a framework tailored to your very specific needs (just be sure
2424
first that your needs are really specific);
@@ -34,55 +34,55 @@ a few good reasons to start creating your own framework:
3434

3535
This tutorial will gently guide you through the creation of a web framework,
3636
one step at a time. At each step, you will have a fully-working framework that
37-
you can use as is or as a start for your very own. We will start with simple
38-
frameworks and more features will be added with time. Eventually, you will have
37+
you can use as is or as a start for your very own. It will start with a simple
38+
framework and more features will be added with time. Eventually, you will have
3939
a fully-featured full-stack web framework.
4040

4141
And of course, each step will be the occasion to learn more about some of the
42-
Symfony2 Components.
42+
Symfony Components.
4343

4444
.. tip::
4545

4646
If you don't have time to read the whole book, or if you want to get
4747
started fast, you can also have a look at `Silex`_, a micro-framework
48-
based on the Symfony2 Components. The code is rather slim and it leverages
49-
many aspects of the Symfony2 Components.
50-
51-
Many modern web frameworks advertize themselves as being MVC frameworks. We
52-
won't talk about the MVC pattern as the Symfony2 Components are able to create
53-
any type of frameworks, not just the ones that follow the MVC architecture.
54-
Anyway, if you have a look at the MVC semantics, this book is about how to
55-
create the Controller part of a framework. For the Model and the View, it
56-
really depends on your personal taste and you can use any existing
57-
third-party libraries (Doctrine, Propel, or plain-old PDO for the Model; PHP
58-
or Twig for the View).
48+
based on the Symfony Components. The code is rather slim and it leverages
49+
many aspects of the Symfony Components.
50+
51+
Many modern web frameworks advertize themselves as being MVC frameworks. This
52+
tutorial won't talk about the MVC pattern, as the Symfony Components are able to
53+
create any type of frameworks, not just the ones that follow the MVC
54+
architecture. Anyway, if you have a look at the MVC semantics, this book is
55+
about how to create the Controller part of a framework. For the Model and the
56+
View, it really depends on your personal taste and you can use any existing
57+
third-party libraries (Doctrine, Propel or plain-old PDO for the Model; PHP or
58+
Twig for the View).
5959

6060
When creating a framework, following the MVC pattern is not the right goal. The
6161
main goal should be the **Separation of Concerns**; this is probably the only
6262
design pattern that you should really care about. The fundamental principles of
63-
the Symfony2 Components are focused on the HTTP specification. As such, the
64-
frameworks that we are going to create should be more accurately labelled as
65-
HTTP frameworks or Request/Response frameworks.
63+
the Symfony Components are focused on the HTTP specification. As such, the
64+
framework that you are going to create should be more accurately labelled as a
65+
HTTP framework or Request/Response framework.
6666

67-
Before we start
68-
---------------
67+
Before You Start
68+
----------------
6969

7070
Reading about how to create a framework is not enough. You will have to follow
71-
along and actually type all the examples we will work on. For that, you need a
72-
recent version of PHP (5.3.8 or later is good enough), a web server (like
73-
Apache or NGinx), a good knowledge of PHP and an understanding of Object
74-
Oriented programming.
71+
along and actually type all the examples included in this tutorial. For that,
72+
you need a recent version of PHP (5.3.9 or later is good enough), a web server
73+
(like Apache, NGinx or PHP's built-in web server), a good knowledge of PHP and
74+
an understanding of Object Oriented programming.
7575

76-
Ready to go? Let's start.
76+
Ready to go? Read on!
7777

7878
Bootstrapping
7979
-------------
8080

81-
Before we can even think of creating our first framework, we need to talk
82-
about some conventions: where we will store our code, how we will name our
83-
classes, how we will reference external dependencies, etc.
81+
Before you can even think of creating the first framework, you need to think
82+
about some conventions: where you will store the code, how you will name the
83+
classes, how you will reference external dependencies, etc.
8484

85-
To store our framework, create a directory somewhere on your machine:
85+
To store your new framework, create a directory somewhere on your machine:
8686

8787
.. code-block:: bash
8888
@@ -92,20 +92,9 @@ To store our framework, create a directory somewhere on your machine:
9292
Dependency Management
9393
~~~~~~~~~~~~~~~~~~~~~
9494

95-
To install the Symfony2 Components that we need for our framework, we are going
95+
To install the Symfony Components that you need for your framework, you are going
9696
to use `Composer`_, a project dependency manager for PHP. If you don't have it
97-
yet, `download and install`_ Composer now:
98-
99-
.. code-block:: bash
100-
101-
$ curl -sS https://getcomposer.org/installer | php
102-
103-
Then, generate an empty ``composer.json`` file, where Composer will store the
104-
framework dependencies:
105-
106-
.. code-block:: bash
107-
108-
$ composer init -n
97+
yet, :doc:`download and install Composer </cookbook/composer>` now.
10998

11099
Our Project
111100
-----------
@@ -114,16 +103,15 @@ Instead of creating our framework from scratch, we are going to write the same
114103
"application" over and over again, adding one abstraction at a time. Let's
115104
start with the simplest web application we can think of in PHP::
116105

117-
<?php
118-
119106
// framework/index.php
120107

121108
$input = $_GET['name'];
122109

123110
printf('Hello %s', $input);
124111

125-
Use the PHP built-in server to test this great application in a browser
126-
(``http://localhost:4321/index.php?name=Fabien``):
112+
If you have PHP 5.4, you can use the PHP built-in server to test this great
113+
application in a browser (``http://localhost:4321/index.php?name=Fabien``).
114+
Otherwise, use your own server (Apache, Nginx, etc.):
127115

128116
.. code-block:: bash
129117
@@ -132,8 +120,7 @@ Use the PHP built-in server to test this great application in a browser
132120
In the next chapter, we are going to introduce the HttpFoundation Component
133121
and see what it brings us.
134122

135-
.. _`Symfony2`: http://symfony.com/
123+
.. _`Symfony`: http://symfony.com/
136124
.. _`documentation`: http://symfony.com/doc
137125
.. _`Silex`: http://silex.sensiolabs.org/
138126
.. _`Composer`: http://packagist.org/about-composer
139-
.. _`download and install`: https://getcomposer.org/doc/01-basic-usage.md

create_framework/02-http-foundation.rst

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Before diving into the framework creation process, let's first step back and
55
let's take a look at why you would like to use a framework instead of keeping
66
your plain-old PHP applications as is. Why using a framework is actually a good
77
idea, even for the simplest snippet of code and why creating your framework on
8-
top of the Symfony2 components is better than creating a framework from scratch.
8+
top of the Symfony components is better than creating a framework from scratch.
99

1010
.. note::
1111

@@ -17,8 +17,6 @@ top of the Symfony2 components is better than creating a framework from scratch.
1717
Even if the "application" we wrote in the previous chapter was simple enough,
1818
it suffers from a few problems::
1919

20-
<?php
21-
2220
// framework/index.php
2321

2422
$input = $_GET['name'];
@@ -28,8 +26,6 @@ it suffers from a few problems::
2826
First, if the ``name`` query parameter is not defined in the URL query string,
2927
you will get a PHP warning; so let's fix it::
3028

31-
<?php
32-
3329
// framework/index.php
3430

3531
$input = isset($_GET['name']) ? $_GET['name'] : 'World';
@@ -40,8 +36,6 @@ Then, this *application is not secure*. Can you believe it? Even this simple
4036
snippet of PHP code is vulnerable to one of the most widespread Internet
4137
security issue, XSS (Cross-Site Scripting). Here is a more secure version::
4238

43-
<?php
44-
4539
$input = isset($_GET['name']) ? $_GET['name'] : 'World';
4640

4741
header('Content-Type: text/html; charset=utf-8');
@@ -65,8 +59,6 @@ much to test, it strikes me that writing unit tests for the simplest possible
6559
snippet of PHP code is not natural and feels ugly. Here is a tentative PHPUnit
6660
unit test for the above code::
6761

68-
<?php
69-
7062
// framework/test.php
7163

7264
class IndexTest extends \PHPUnit_Framework_TestCase
@@ -86,8 +78,8 @@ unit test for the above code::
8678
.. note::
8779

8880
If our application were just slightly bigger, we would have been able to
89-
find even more problems. If you are curious about them, read the `Symfony2
90-
versus Flat PHP`_ chapter of the Symfony2 documentation.
81+
find even more problems. If you are curious about them, read the `Symfony
82+
versus Flat PHP`_ chapter of the Symfony documentation.
9183

9284
At this point, if you are not convinced that security and testing are indeed
9385
two very good reasons to stop writing code the old way and adopt a framework
@@ -117,7 +109,7 @@ In PHP, the request is represented by global variables (``$_GET``, ``$_POST``,
117109
functions (``echo``, ``header``, ``setcookie``, ...).
118110

119111
The first step towards better code is probably to use an Object-Oriented
120-
approach; that's the main goal of the Symfony2 HttpFoundation component:
112+
approach; that's the main goal of the Symfony HttpFoundation component:
121113
replacing the default PHP global variables and functions by an Object-Oriented
122114
layer.
123115

@@ -141,8 +133,6 @@ HttpFoundation component and install it under the ``vendor/`` directory.
141133
Now, let's rewrite our application by using the ``Request`` and the
142134
``Response`` classes::
143135

144-
<?php
145-
146136
// framework/index.php
147137

148138
require_once __DIR__.'/vendor/autoload.php';
@@ -184,8 +174,6 @@ charge of sending the response whenever you see fit.
184174
With the ``Request`` class, you have all the request information at your
185175
fingertips thanks to a nice and simple API::
186176

187-
<?php
188-
189177
// the URI being requested (e.g. /about) minus any query parameters
190178
$request->getPathInfo();
191179

@@ -215,8 +203,6 @@ You can also simulate a request::
215203

216204
With the ``Response`` class, you can easily tweak the response::
217205

218-
<?php
219-
220206
$response = new Response();
221207

222208
$response->setContent('Hello world!');
@@ -240,8 +226,6 @@ framework?
240226

241227
Even something as simple as getting the client IP address can be insecure::
242228

243-
<?php
244-
245229
if ($myIp == $_SERVER['REMOTE_ADDR']) {
246230
// the client is a known one, so give it some more privilege
247231
}
@@ -251,8 +235,6 @@ production servers; at this point, you will have to change your code to make
251235
it work on both your development machine (where you don't have a proxy) and
252236
your servers::
253237

254-
<?php
255-
256238
if ($myIp == $_SERVER['HTTP_X_FORWARDED_FOR'] || $myIp == $_SERVER['REMOTE_ADDR']) {
257239
// the client is a known one, so give it some more privilege
258240
}
@@ -261,8 +243,6 @@ Using the ``Request::getClientIp()`` method would have given you the right
261243
behavior from day one (and it would have covered the case where you have
262244
chained proxies)::
263245

264-
<?php
265-
266246
$request = Request::createFromGlobals();
267247

268248
if ($myIp == $request->getClientIp()) {
@@ -276,8 +256,6 @@ code in production without a proxy, it becomes trivially easy to abuse your
276256
system. That's not the case with the ``getClientIp()`` method as you must
277257
explicitly trust your reverse proxies by calling ``setTrustedProxies()``::
278258

279-
<?php
280-
281259
Request::setTrustedProxies(array('10.0.0.1'));
282260

283261
if ($myIp == $request->getClientIp(true)) {
@@ -297,7 +275,7 @@ cases by yourself. Why not using a technology that already works?
297275
its dedicated :doc:`documentation </components/http_foundation/index>`.
298276

299277
Believe or not but we have our first framework. You can stop now if you want.
300-
Using just the Symfony2 HttpFoundation component already allows you to write
278+
Using just the Symfony HttpFoundation component already allows you to write
301279
better and more testable code. It also allows you to write code faster as many
302280
day-to-day problems have already been solved for you.
303281

@@ -307,14 +285,14 @@ the wheel.
307285

308286
I've almost forgot to talk about one added benefit: using the HttpFoundation
309287
component is the start of better interoperability between all frameworks and
310-
applications using it (like `Symfony2`_, `Drupal 8`_, `phpBB 4`_, `ezPublish
288+
applications using it (like `Symfony`_, `Drupal 8`_, `phpBB 4`_, `ezPublish
311289
5`_, `Laravel`_, `Silex`_, and `more`_).
312290

313291
.. _`Twig`: http://twig.sensiolabs.com/
314-
.. _`Symfony2 versus Flat PHP`: http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html
292+
.. _`Symfony versus Flat PHP`: http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html
315293
.. _`HTTP specification`: http://tools.ietf.org/wg/httpbis/
316294
.. _`audited`: http://symfony.com/blog/symfony2-security-audit
317-
.. _`Symfony2`: http://symfony.com/
295+
.. _`Symfony`: http://symfony.com/
318296
.. _`Drupal 8`: http://drupal.org/
319297
.. _`phpBB 4`: http://www.phpbb.com/
320298
.. _`ezPublish 5`: http://ez.no/

create_framework/03-front-controller.rst

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ Up until now, our application is simplistic as there is only one page. To
55
spice things up a little bit, let's go crazy and add another page that says
66
goodbye::
77

8-
<?php
9-
108
// framework/bye.php
119

1210
require_once __DIR__.'/vendor/autoload.php';
@@ -27,8 +25,6 @@ our first "real" framework!
2725
The PHP way of doing the refactoring would probably be the creation of an
2826
include file::
2927

30-
<?php
31-
3228
// framework/init.php
3329

3430
require_once __DIR__.'/vendor/autoload.php';
@@ -41,8 +37,6 @@ include file::
4137

4238
Let's see it in action::
4339

44-
<?php
45-
4640
// framework/index.php
4741

4842
require_once __DIR__.'/init.php';
@@ -54,8 +48,6 @@ Let's see it in action::
5448

5549
And for the "Goodbye" page::
5650

57-
<?php
58-
5951
// framework/bye.php
6052

6153
require_once __DIR__.'/init.php';
@@ -83,8 +75,6 @@ routing all client requests to a single PHP script.
8375

8476
Such a script might look like the following::
8577

86-
<?php
87-
8878
// framework/front.php
8979

9080
require_once __DIR__.'/vendor/autoload.php';
@@ -112,8 +102,6 @@ Such a script might look like the following::
112102

113103
And here is for instance the new ``hello.php`` script::
114104

115-
<?php
116-
117105
// framework/hello.php
118106

119107
$input = $request->get('name', 'World');
@@ -185,8 +173,6 @@ The last thing that is repeated in each page is the call to ``setContent()``.
185173
We can convert all pages to "templates" by just echoing the content and calling
186174
the ``setContent()`` directly from the front controller script::
187175

188-
<?php
189-
190176
// example.com/web/front.php
191177

192178
// ...
@@ -213,8 +199,6 @@ And the ``hello.php`` script can now be converted to a template::
213199

214200
We have the first version of our framework::
215201

216-
<?php
217-
218202
// example.com/web/front.php
219203

220204
require_once __DIR__.'/../vendor/autoload.php';

0 commit comments

Comments
 (0)