Skip to content

[book] 1st to 4th ch changes #6252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 85 additions & 51 deletions book/from_flat_php_to_symfony2.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
.. index::
single: Symfony versus Flat PHP

.. _symfony2-versus-flat-php:

Symfony versus Flat PHP
=======================

**Why is Symfony better than just opening up a file and writing flat PHP?**

If you've never used a PHP framework, aren't familiar with the MVC philosophy,
or just wonder what all the *hype* is around Symfony, this chapter is for
you. Instead of *telling* you that Symfony allows you to develop faster and
better software than with flat PHP, you'll see for yourself.
If you've never used a PHP framework, aren't familiar with the
model-view-controller `MVC`_ philosophy, or just wonder what all the *hype*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change this to: "Model-View-Controller (MVC) philosophy" also, we don't use a serial comma (the one before "or") in the docs. Although that isn't your fault, it would be nice to include it in this PR

is around Symfony, this chapter is for you. Instead of *telling* you that
Symfony allows you to develop faster and better software than with flat PHP,
you'll see for yourself.

In this chapter, you'll write a simple application in flat PHP, and then
refactor it to be more organized. You'll travel through time, seeing the
Expand Down Expand Up @@ -103,6 +107,7 @@ is primarily an HTML file that uses a template-like PHP syntax:

.. code-block:: html+php

<!-- templates/list.php -->
<!DOCTYPE html>
<html>
<head>
Expand Down Expand Up @@ -179,6 +184,7 @@ of the application are isolated in a new file called ``model.php``::

The controller (``index.php``) is now very simple::

// index.php
require_once 'model.php';

$posts = get_all_posts();
Expand All @@ -197,7 +203,7 @@ offering various advantages and the opportunity to reuse almost everything
on different pages.

The only part of the code that *can't* be reused is the page layout. Fix
that by creating a new ``layout.php`` file:
that by creating a new ``templates/layout.php`` file:

.. code-block:: html+php

Expand All @@ -217,6 +223,7 @@ the layout:

.. code-block:: html+php

<!-- templates/list.php -->
<?php $title = 'List of Posts' ?>

<?php ob_start() ?>
Expand All @@ -237,8 +244,9 @@ the layout:
You now have a setup that will allow you to reuse the layout.
Unfortunately, to accomplish this, you're forced to use a few ugly
PHP functions (``ob_start()``, ``ob_get_clean()``) in the template. Symfony
uses a Templating component that allows this to be accomplished cleanly
and easily. You'll see it in action shortly.
uses a :doc:`Templating </components/templating/introduction>` component
that allows this to be accomplished cleanly and easily. You'll see it in
action shortly.

Adding a Blog "show" Page
-------------------------
Expand All @@ -248,7 +256,7 @@ and reusable. To prove it, add a blog "show" page, which displays an individual
blog post identified by an ``id`` query parameter.

To begin, create a new function in the ``model.php`` file that retrieves
an individual blog result based on a given id::
an individual blog result based on a given ``id``::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to be a code block here actually


// model.php
function get_post_by_id($id)
Expand All @@ -266,6 +274,7 @@ an individual blog result based on a given id::
Next, create a new file called ``show.php`` - the controller for this new
page::

// show.php
require_once 'model.php';

$post = get_post_by_id($_GET['id']);
Expand All @@ -277,6 +286,7 @@ the individual blog post:

.. code-block:: html+php

<!-- templates/show.php -->
<?php $title = $post['title'] ?>

<?php ob_start() ?>
Expand All @@ -295,8 +305,8 @@ this page introduces even more lingering problems that a framework can solve
for you. For example, a missing or invalid ``id`` query parameter will cause
the page to crash. It would be better if this caused a 404 page to be rendered,
but this can't really be done easily yet. Worse, had you forgotten to clean
the ``id`` parameter via the ``intval()`` function, your
entire database would be at risk for an SQL injection attack.
the ``id`` parameter via the PHP ``intval()`` function, your
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the readflow is a bit better if we put "PHP" after the function name: "intval() PHP function"

entire database would be at risk for an `SQL injection attack`_.

Another major problem is that each individual controller file must include
the ``model.php`` file. What if each controller file suddenly needed to include
Expand Down Expand Up @@ -325,9 +335,10 @@ application change slightly, but start to become more flexible:
/index.php/show => Blog post show page (index.php executed)

.. tip::
The ``index.php`` portion of the URI can be removed if using Apache
rewrite rules (or equivalent). In that case, the resulting URI of the
blog show page would be simply ``/show``.

Using Apache's ``mod_rewrite`` (or equivalent with other web servers),
the URL can easily be cleaned up - ``index.php`` portion removed -
to be just ``/show``.

When using a front controller, a single PHP file (``index.php`` in this case)
renders *every* request. For the blog post show page, ``/index.php/show`` will
Expand Down Expand Up @@ -362,8 +373,12 @@ on the requested URI::
}

For organization, both controllers (formerly ``index.php`` and ``show.php``)
are now PHP functions and each has been moved into a separate file, ``controllers.php``::
are now PHP functions and each has been moved into a separate file named
``controllers.php``. The job of each PHP function, now called a
:term:`controller`, is to use information from the ``Request`` object to create
and return a ``Response`` object.::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either end with double colon (which will render as a single one) or end with a final stop (.) and use .. code-block:: php on a new line


// controllers.php
function list_action()
{
$posts = get_all_posts();
Expand All @@ -382,6 +397,14 @@ one of the two controllers (the ``list_action()`` and ``show_action()``
functions) is called. In reality, the front controller is beginning to look and
act a lot like Symfony's mechanism for handling and routing requests.

.. note::

Though similarly named, a "front controller" is different from the PHP functions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be removed, as it would break existing anchors (this is precisely why it was added)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked for the existing anchors and there are non, thou they might be on other branches. True.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anchors can be used by other sites to link to particular sections of the docs. That's why we keep them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked the whole Internet for links pointing to this page and using an anchor ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that. Noted.

called "controllers" talked about in this chapter. A front controller is a short PHP
file through which all requests are directed. "Controller" functions are grouped in
several files and they hold your code which creates and returns the appropriate
``Response`` object. Controllers are also called *actions*.

.. tip::

Another advantage of a front controller is flexible URLs. Notice that
Expand All @@ -391,21 +414,19 @@ act a lot like Symfony's mechanism for handling and routing requests.

By now, the application has evolved from a single PHP file into a structure
that is organized and allows for code reuse. You should be happier, but far
from satisfied. For example, the "routing" system is fickle, and wouldn't
from satisfied. For example, the routing system is fickle, and wouldn't
recognize that the list page (``/index.php``) should be accessible also via ``/``
(if Apache rewrite rules were added). Also, instead of developing the blog,
a lot of time is being spent working on the "architecture" of the code (e.g.
routing, calling controllers, templates, etc.). More time will need to be
spent to handle form submissions, input validation, logging and security.
Why should you have to reinvent solutions to all these routine problems?

.. _add-a-touch-of-symfony2:

Add a Touch of Symfony
~~~~~~~~~~~~~~~~~~~~~~

Symfony to the rescue. Before actually using Symfony, you need to download
it. This can be done by using Composer, which takes care of downloading the
it. This can be done by using `Composer`_, which takes care of downloading the
correct version and all its dependencies and provides an autoloader. An
autoloader is a tool that makes it possible to start using PHP classes
without explicitly including the file containing the class.
Expand All @@ -425,7 +446,7 @@ content:
}

Next, `download Composer`_ and then run the following command, which will download Symfony
into a vendor/ directory:
into a ``vendor/`` directory:

.. code-block:: bash

Expand Down Expand Up @@ -509,17 +530,17 @@ allowing HTTP headers and content to be added via an object-oriented interface.
And while the responses in this application are simple, this flexibility
will pay dividends as your application grows.

.. _the-sample-application-in-symfony2:

The Sample Application in Symfony
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The blog has come a *long* way, but it still contains a lot of code for such
a simple application. Along the way, you've made a simple routing
system and a method using ``ob_start()`` and ``ob_get_clean()`` to render
templates. If, for some reason, you needed to continue building this "framework"
from scratch, you could at least use Symfony's standalone `Routing`_ and
`Templating`_ components, which already solve these problems.
from scratch, you could at least use Symfony's standalone
:doc:`Routing </components/routing/introduction>` and
:doc:`Templating </components/templating/introduction>` components, which already
solve these problems.

Instead of re-solving common problems, you can let Symfony take care of
them for you. Here's the same sample application, now built in Symfony::
Expand Down Expand Up @@ -557,10 +578,15 @@ them for you. Here's the same sample application, now built in Symfony::
}
}

First we have a "controller class" which is a convenient way to group several
"controllers" together. So methods inside a controller class are controllers
also called *actions*. They hold code which creates and returns the appropriate
``Response`` object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should talk about controllers and actions and their differences at this point. It's just a very very quick introduction article into Symfony. Such detailed things should be discussed in the main book chapters (e.g. "Controllers") imo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this based on my personal experience... When i was introduced to Symfony and start reading the documentation i had trouble understanding this chapter and the controller concept - diff between flat PHP and Symfony controllers - because of this missing information that didn't appeared until in some later chapter.. Word controller is used thought the chapter and it does not always refer to the same thing. So i think that to a newcomer it's quite unclear if it doesn't have any background in web dev and essential to understand what it's actually meant.
Do you think i should still through this out?


The two controllers are still lightweight. Each uses the
:doc:`Doctrine ORM library </book/doctrine>` to retrieve objects from the
database and the Templating component to render a template and return a
``Response`` object. The list template is now quite a bit simpler:
``Response`` object. The list (``list.php``) template is now quite a bit simpler:

.. code-block:: html+php

Expand All @@ -583,7 +609,7 @@ database and the Templating component to render a template and return a
<?php endforeach ?>
</ul>

The layout is nearly identical:
The layout (``layout.php``) is nearly identical:

.. code-block:: html+php

Expand All @@ -603,12 +629,13 @@ The layout is nearly identical:

.. note::

The show template is left as an exercise, as it should be trivial to
create based on the list template.
The show (``show.php``) template is left as an exercise, as it should be trivial to
create based on the list (``list.php``) template.

When Symfony's engine (called the ``Kernel``) boots up, it needs a map so
When Symfony's engine (called the :term:`Kernel`) boots up, it needs a map so
that it knows which controllers to execute based on the request information.
A routing configuration map provides this information in a readable format:
A routing configuration map ``app/config/routing.yml`` provides this information
in a readable format:

.. code-block:: yaml

Expand All @@ -622,9 +649,9 @@ A routing configuration map provides this information in a readable format:
defaults: { _controller: AppBundle:Blog:show }

Now that Symfony is handling all the mundane tasks, the front controller
is dead simple. And since it does so little, you'll never have to touch
it once it's created (and if you use a `Symfony distribution`_, you won't
even need to create it!)::
``web/app.php`` is dead simple. And since it does so little, you'll never
have to touch it once it's created (and if you use a `Symfony distribution`_,
you won't even need to create it!)::

// web/app.php
require_once __DIR__.'/../app/bootstrap.php';
Expand All @@ -635,16 +662,18 @@ even need to create it!)::
$kernel = new AppKernel('prod', false);
$kernel->handle(Request::createFromGlobals())->send();

The front controller's only job is to initialize Symfony's engine (``Kernel``)
and pass it a ``Request`` object to handle. Symfony's core then uses the
routing map to determine which controller to call. Just like before, the
controller method is responsible for returning the final ``Response`` object.
There's really not much else to it.
Front controller's only job is to initialize Symfony's engine (called the
:term:`Kernel`) and pass it a ``Request`` object to handle. The Symfony core
asks the router to inspect the request. The router matches the incoming URL
to a specific route and returns information about the route, including the
controller that should be executed. The correct controller from the matched
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this also too specific and too focussed on the implementation for a getting started docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do u want me to just revert or should I also remove the original text with (or without) the picture?

route is executed and the code inside the controller creates and returns the
appropriate ``Response`` object. The HTTP headers and content of the ``Response``
object are sent back to the client.

For a visual representation of how Symfony handles each request, see the
:ref:`request flow diagram <request-flow-figure>`.

.. _where-symfony2-delivers:
.. figure:: /images/request-flow.png
:align: center
:alt: Symfony request flow

Where Symfony Delivers
~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -661,8 +690,11 @@ at how migrating the blog from flat PHP to Symfony has improved life:
to develop or maintain low-level utilities** such as autoloading,
:doc:`routing </book/routing>`, or rendering :doc:`controllers </book/controller>`;

* Symfony gives you **access to open source tools** such as Doctrine and the
Templating, Security, Form, Validation and Translation components (to name
* Symfony gives you **access to open source tools** such as `Doctrine`_ and the
:doc:`Templating </components/templating/introduction>`,
:doc:`Security </components/security/introduction>`,
:doc:`Form </components/form/introduction>`, `Validator`_ and
:doc:`Translation </components/translation/introduction>` components (to name
a few);

* The application now enjoys **fully-flexible URLs** thanks to the Routing
Expand All @@ -683,7 +715,7 @@ Better Templates
If you choose to use it, Symfony comes standard with a templating engine
called `Twig`_ that makes templates faster to write and easier to read.
It means that the sample application could contain even less code! Take,
for example, the list template written in Twig:
for example, lets rewrite ``layout.html.php`` template in Twig:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we never use lets in the doc AFAIK (and it should be let's anyway if you use it)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, we should avoid first person usage in all docs (apart from best practices and quick tour)


.. code-block:: html+twig

Expand All @@ -705,7 +737,7 @@ for example, the list template written in Twig:
</ul>
{% endblock %}

The corresponding ``layout.html.twig`` template is also easier to write:
The corresponding ``layout.html.php`` template is also easier to write in Twig:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is wrong. The template name ends with .twig, not .php

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually if you look up closely , in these chapter you first write layout.html.php and list.html.php and then, where i made a change, you rewrite these to templates with Twig.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I don't fully get your changes here. Line 718 now says "lets rewrite layout.html.php template in Twig:" and directly after it, you have this line also mentioning "The corresponding layout.html.php template is also easier to write in Twig:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked again. On the 718th line it should be list.html.php and then on the 740th line it should be layout.html.php but without "corresponding" which adds a bit of confusion.
The chapter flow is:

  1. create list and layout .php file
  2. rewrite them in *.html.php
  3. and finally rewrite them in *.html.twig


.. code-block:: html+twig

Expand All @@ -730,12 +762,14 @@ Learn more from the Cookbook
* :doc:`/cookbook/templating/PHP`
* :doc:`/cookbook/controller/service`


.. _`MVC`: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
.. _`Doctrine`: http://www.doctrine-project.org
.. _`SQL injection attack`: https://en.wikipedia.org/wiki/SQL_injection
.. _`Composer`: https://getcomposer.org
.. _`download Composer`: https://getcomposer.org/download/
.. _`Routing`: https://github.com/symfony/routing
.. _`Templating`: https://github.com/symfony/templating
.. _`KnpBundles.com`: http://knpbundles.com/
.. _`Twig`: http://twig.sensiolabs.org
.. _`Varnish`: https://www.varnish-cache.org/
.. _`PHPUnit`: http://www.phpunit.de
.. _`Symfony distribution`: https://github.com/symfony/symfony-standard
.. _`Validator`: https://github.com/symfony/validator
.. _`Varnish`: https://www.varnish-cache.org/
.. _`KnpBundles.com`: http://knpbundles.com/
.. _`Twig`: http://twig.sensiolabs.org
Loading