Skip to content

Commit

Permalink
updated the whole book (changes mainly related to Composer)
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Jun 23, 2014
1 parent 842e4d1 commit 55f5c12
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 117 deletions.
59 changes: 22 additions & 37 deletions book/part01.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,44 +94,23 @@ To store our framework, create a directory somewhere on your machine:
$ mkdir framework
$ cd framework
Components Installation
~~~~~~~~~~~~~~~~~~~~~~~
Dependency Management
~~~~~~~~~~~~~~~~~~~~~

To install the Symfony2 Components that we need for our framework, we are
going to use `Composer`_, a project dependency manager for PHP. Create a
``composer.json`` file, where we will list our dependencies:

.. code-block:: javascript
{
"require": {
}
}
The file is empty for now as we do not depend on anything yet. To install the
project dependencies, download the composer binary and run it:
To install the Symfony2 Components that we need for our framework, we are going
to use `Composer`_, a project dependency manager for PHP. If you don't have it
yet, `download and install`_ Composer now:

.. code-block:: sh
$ wget http://getcomposer.org/composer.phar
$ # or
$ curl -O http://getcomposer.org/composer.phar
$ php composer.phar install
After running the ``install`` command, you must see a new ``vendor/``
directory.
$ curl -sS https://getcomposer.org/installer | php
Naming Conventions and Autoloading
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Then, generate an empty ``composer.json`` file, where Composer will store the
framework dependencies:

We are going to `autoload`_ all our classes. Without autoloading, you need to
require the file where a class is defined before being able to use it. But
with some conventions, we can just let PHP do the hard work for us.
.. code-block:: sh
Symfony2 follows the de-facto PHP standard, `PSR-0`_, for class names and
autoloading and Composer generates such an autoloader for all the dependencies
it manages; it can be enabled by requiring the ``vendor/autoload.php`` file.
$ php composer.phar init -n
Our Project
-----------
Expand All @@ -148,12 +127,18 @@ start with the simplest web application we can think of in PHP::

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

Use the PHP built-in server to test this great application in a browser
(``http://localhost:4321/index.php?name=Fabien``):

.. code-block:: sh
$ php -S 127.0.0.1:4321
In the next chapter, we are going to introduce the HttpFoundation Component
and see what it brings us.

.. _`Symfony2`: http://symfony.com/
.. _`documentation`: http://symfony.com/doc
.. _`Silex`: http://silex.sensiolabs.org/
.. _`autoload`: http://fr.php.net/autoload
.. _`Composer`: http://packagist.org/about-composer
.. _`PSR-0`: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
.. _`Symfony2`: http://symfony.com/
.. _`documentation`: http://symfony.com/doc
.. _`Silex`: http://silex.sensiolabs.org/
.. _`Composer`: http://packagist.org/about-composer
.. _`download and install`: https://getcomposer.org/doc/01-basic-usage.md
31 changes: 17 additions & 14 deletions book/part02.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ it suffers from a few problems::

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

First, if the ``name`` query parameter is not given in the URL query string,
First, if the ``name`` query parameter is not defined in the URL query string,
you will get a PHP warning; so let's fix it::

<?php
Expand Down Expand Up @@ -122,22 +122,22 @@ approach; that's the main goal of the Symfony2 HttpFoundation component:
replacing the default PHP global variables and functions by an Object-Oriented
layer.

To use this component, open the ``composer.json`` file and add it as a
dependency for the project:
To use this component, add it as a dependency of the project:

.. code-block:: javascript
.. code-block:: sh
{
"require": {
"symfony/http-foundation": "~2.3"
}
}
$ php composer.phar require symfony/http-foundation 2.5.*
Then, run the composer ``update`` command:
Running this command will also automatically download the Symfony
HttpFoundation component and install it under the ``vendor/`` directory.

.. code-block:: sh
.. sidebar:: Class Autoloading

$ php composer.phar update
When installing a new dependency, Composer also generates a
``vendor/autoload.php`` file that allows any class to be easily
`autoloaded`_. Without autoloading, you would need to require the file
where a class is defined before being able to use it. But thanks to
`PSR-0`_, we can just let Composer and PHP do the hard work for us.

Now, let's rewrite our application by using the ``Request`` and the
``Response`` classes::
Expand Down Expand Up @@ -309,8 +309,8 @@ 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
applications using it (as of today `Symfony2`_, `Drupal 8`_, `phpBB 4`_,
`ezPublish 5`, `Silex`_, `Midgard CMS`_, `Zikula`_ ...).
applications using it (like `Symfony2`_, `Drupal 8`_, `phpBB 4`_, `ezPublish
5`, `Laravel`_, `Silex`_, and `more`_).

.. _`Twig`: http://twig.sensiolabs.com/
.. _`Symfony2 versus Flat PHP`: http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html
Expand All @@ -324,3 +324,6 @@ applications using it (as of today `Symfony2`_, `Drupal 8`_, `phpBB 4`_,
.. _`Silex`: http://silex.sensiolabs.org/
.. _`Midgard CMS`: http://www.midgard-project.org/
.. _`Zikula`: http://zikula.org/
.. _`autoloaded`: http://php.net/autoload
.. _`PSR-0`: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
.. _`more`: http://symfony.com/components/HttpFoundation
34 changes: 20 additions & 14 deletions book/part03.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ And for the "Goodbye" page::
$response->send();

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 do not look like templates, and
we are still not able to test this code properly.
not feel like a good abstraction, does it? We still have the ``send()`` method
for all pages, 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
(``http://example.com/bye.php``): there is a direct mapping between the PHP
(``http://127.0.0.1:4321/bye.php``): there is a direct mapping between the PHP
script name and the client URL. This is because the dispatching of the request
is done by the web server directly. It might be a good idea to move this
dispatching to our code for better flexibility. This can be easily achieved by
Expand Down Expand Up @@ -127,18 +127,17 @@ we return a custom 404 page; you are now in control of your website.

To access a page, you must now use the ``front.php`` script:

* ``http://example.com/front.php/hello?name=Fabien``
* ``http://127.0.0.1:4321/front.php/hello?name=Fabien``

* ``http://example.com/front.php/bye``
* ``http://127.0.0.1:4321/front.php/bye``

``/hello`` and ``/bye`` are the page *path*s.
.. tip::

Most web servers like Apache or nginx are able to rewrite the incoming
URLs and remove the front controller script so that your users will be
able to type ``http://example.com/hello?name=Fabien``, which looks much
better.
Most web servers like Apache or nginx are able to rewrite the incoming URLs
and remove the front controller script so that your users will be able to
type ``http://127.0.0.1:4321/hello?name=Fabien``, which looks much better.

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
Expand All @@ -152,8 +151,8 @@ its sub-directories (only if needed -- see above tip).
argument is the URL path you want to simulate.

Now that the web server always access the same script (``front.php``) for all
our pages, we can secure our code further by moving all other PHP files
outside the web root directory:
pages, we can secure the code further by moving all other PHP files outside the
web root directory:

.. code-block:: text
Expand All @@ -170,14 +169,21 @@ outside the web root directory:
Now, configure your web server root directory to point to ``web/`` and all
other files won't be accessible from the client anymore.

To test your changes in a browser (``http://localhost:4321/?name=Fabien``), run
the PHP built-in server:

.. code-block:: sh
$ php -S 127.0.0.1:4321 -t web/ web/front.php
.. note::

For this new structure to work, you will have to adjust some paths in
various PHP files; the changes are left as an exercise for the reader.

The last thing that is repeated in each page is the call to ``setContent()``.
We can convert all pages to "templates" by just echoing the content and
calling the ``setContent()`` directly from the front controller script::
We can convert all pages to "templates" by just echoing the content and calling
the ``setContent()`` directly from the front controller script::

<?php

Expand Down
13 changes: 3 additions & 10 deletions book/part04.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,11 @@ instead of relying on a query string:
# After
/hello/Fabien

To support this feature, we are going to use the Symfony2 Routing component.
As always, add it to ``composer.json`` and run the ``php composer.phar
update`` command to install it:
To support this feature, add the Symfony2 Routing component as a dependency:

.. code-block:: javascript
.. code-block:: sh
{
"require": {
"symfony/http-foundation": "~2.3",
"symfony/routing": "~2.3"
}
}
$ php composer.phar require symfony/routing 2.5.*
Instead of an array for the URL map, the Routing component relies on a
``RouteCollection`` instance::
Expand Down
12 changes: 4 additions & 8 deletions book/part06.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,11 @@ lazy-loaded so that only the controller associated with the matched route is
instantiated.

To solve this issue, and a bunch more, let's install and use the HttpKernel
component::
component:

{
"require": {
"symfony/http-foundation": "~2.3",
"symfony/routing": "~2.3",
"symfony/http-kernel": "~2.3"
}
}
.. code-block:: sh
$ php composer.phar require symfony/http-kernel 2.5.*
The HttpKernel component has many interesting features, but the one we need
right now is the *controller resolver*. A controller resolver knows how to
Expand Down
14 changes: 6 additions & 8 deletions book/part07.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ Request, and one output, the Response. Our framework class will follow this
simple principle: the logic is about creating the Response associated with a
Request.

As the Symfony2 components requires PHP 5.3, let's create our very own
namespace for our framework: ``Simplex``.

Move the request handling logic into its own ``Simplex\\Framework`` class::
Let's create our very own namespace for our framework: ``Simplex``. Move the
request handling logic into its own ``Simplex\\Framework`` class::

<?php

Expand Down Expand Up @@ -89,9 +87,9 @@ be autoloaded, update the ``composer.json`` file:
{
"require": {
"symfony/http-foundation": "~2.3",
"symfony/routing": "~2.3",
"symfony/http-kernel": "~2.3"
"symfony/http-foundation": "2.5.*",
"symfony/routing": "2.5.*",
"symfony/http-kernel": "2.5.*"
},
"autoload": {
"psr-0": { "Simplex\\": "src/", "Calendar\\": "src/" }
Expand All @@ -100,7 +98,7 @@ be autoloaded, update the ``composer.json`` file:
.. note::

For the autoloader to be updated, run ``php composer.phar update``.
For the Composer autoloader to be updated, run ``php composer.phar update``.

Move the controller to ``Calendar\\Controller\\LeapYearController``::

Expand Down
14 changes: 2 additions & 12 deletions book/part09.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,9 @@ pattern, the *Observer*, to allow any kind of behaviors to be attached to our
framework; the Symfony2 EventDispatcher Component implements a lightweight
version of this pattern:

.. code-block:: javascript
.. code-block:: sh
{
"require": {
"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/" }
}
}
$ php composer.phar require symfony/event-dispatcher 2.5.*
How does it work? The *dispatcher*, the central object of the event dispatcher
system, notifies *listeners* of an *event* dispatched to it. Put another way:
Expand Down
17 changes: 3 additions & 14 deletions book/part12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,9 @@ front controller? As you might expect, there is a solution. We can solve all
these issues and some more by using the Symfony2 dependency injection
container:

.. code-block:: javascript
.. code-block:: sh
{
"require": {
"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/" }
}
}
$ php composer.phar require symfony/dependency-injection 2.5.*
Create a new file to host the dependency injection container configuration::

Expand Down Expand Up @@ -244,7 +233,7 @@ definitions, from scope support to dumping a container to a plain PHP class,
and much more. The Symfony dependency injection container is really powerful
and is able to manage any kind of PHP class.

Don't yell at me if you don't want to have a dependency injection container in
Don't yell at me if you don't want to use a dependency injection container in
your framework. If you don't like it, don't use it. It's your framework, not
mine.

Expand Down

0 comments on commit 55f5c12

Please sign in to comment.