-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[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
Changes from 1 commit
58f30b8
5f212cf
224e251
f93de93
546c963
1e22aa8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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* | ||
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 | ||
|
@@ -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> | ||
|
@@ -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(); | ||
|
@@ -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 | ||
|
||
|
@@ -217,6 +223,7 @@ the layout: | |
|
||
.. code-block:: html+php | ||
|
||
<!-- templates/list.php --> | ||
<?php $title = 'List of Posts' ?> | ||
|
||
<?php ob_start() ?> | ||
|
@@ -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 | ||
------------------------- | ||
|
@@ -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``:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
@@ -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']); | ||
|
@@ -277,6 +286,7 @@ the individual blog post: | |
|
||
.. code-block:: html+php | ||
|
||
<!-- templates/show.php --> | ||
<?php $title = $post['title'] ?> | ||
|
||
<?php ob_start() ?> | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: " |
||
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 | ||
|
@@ -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 | ||
|
@@ -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.:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ( |
||
|
||
// controllers.php | ||
function list_action() | ||
{ | ||
$posts = get_all_posts(); | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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. | ||
|
@@ -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 | ||
|
||
|
@@ -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:: | ||
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
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 | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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'; | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
~~~~~~~~~~~~~~~~~~~~~~ | ||
|
@@ -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 | ||
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we never use There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
||
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is wrong. The template name ends with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually if you look up closely , in these chapter you first write There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looked again. On the 718th line it should be
|
||
|
||
.. code-block:: html+twig | ||
|
||
|
@@ -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 |
There was a problem hiding this comment.
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