diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index fcd9eeec193..e297b119872 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -1,3 +1,6 @@ +.. index:: + single: Symfony versus Flat PHP + .. _symfony2-versus-flat-php: Symfony versus Flat PHP @@ -5,10 +8,11 @@ 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 @@ -98,11 +102,12 @@ the code that prepares the HTML "presentation":: require 'templates/list.php'; -The HTML code is now stored in a separate file (``templates/list.php``), which +The HTML code is now stored in a separate file ``templates/list.php``, which is primarily an HTML file that uses a template-like PHP syntax: .. code-block:: html+php + @@ -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 @@ -212,11 +218,12 @@ that by creating a new ``layout.php`` file: -The template (``templates/list.php``) can now be simplified to "extend" -the layout: +The template ``templates/list.php`` can now be simplified to "extend" +the ``templates/layout.php``: .. code-block:: html+php + @@ -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 ` component +that allows this to be accomplished cleanly and easily. You'll see it in +action shortly. Adding a Blog "show" Page ------------------------- @@ -270,6 +278,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']); @@ -281,6 +290,7 @@ the individual blog post: .. code-block:: html+php + @@ -327,9 +337,9 @@ 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``. + + By using rewrite rules in your :doc:`web server configuration `, + the ``index.php`` won't be needed and you will have beautiful, clean URLs (e.g. ``/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 @@ -364,8 +374,9 @@ 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``:: + // controllers.php function list_action() { $posts = get_all_posts(); @@ -382,7 +393,11 @@ As a front controller, ``index.php`` has taken on an entirely new role, one that includes loading the core libraries and routing the application so that 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. +act a lot like how Symfony handles and routes requests. + +But but careful not to confuse the terms *front controller* and *controller*. Your +app will usually have just *one* front controller, which boots your code. You will +have *many* controller functions: one for each page. .. tip:: @@ -393,8 +408,8 @@ 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 -recognize that the list page (``/index.php``) should be accessible also via ``/`` +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 @@ -407,7 +422,7 @@ 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. @@ -427,7 +442,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 @@ -501,7 +516,8 @@ incidentally, acts quite a bit like the Symfony templating engine:: By bringing in a small part of Symfony, the application is more flexible and reliable. The ``Request`` provides a dependable way to access information -about the HTTP request. Specifically, the ``getPathInfo()`` method returns +about the HTTP request. Specifically, the +:method:`Symfony\\Component\\HttpFoundation\\Request::getPathInfo` method returns a cleaned URI (always returning ``/show`` and never ``/index.php/show``). So, even if the user goes to ``/index.php/show``, the application is intelligent enough to route the request through ``show_action()``. @@ -520,8 +536,10 @@ 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 ` and +:doc:`Templating ` 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:: @@ -559,10 +577,14 @@ them for you. Here's the same sample application, now built in Symfony:: } } -The two controllers are still lightweight. Each uses the +Notice, both controller functions now live inside a "controller class". This is a +nice way to group related pages. The controller functions are also sometimes called +*actions*. + +The two controllers (or actions) are still lightweight. Each uses the :doc:`Doctrine ORM library ` 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 @@ -585,7 +607,7 @@ database and the Templating component to render a template and return a -The layout is nearly identical: +The ``layout.php`` file is nearly identical: .. code-block:: html+php @@ -605,12 +627,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: updating it should be + really similar to updating the ``list.php`` template. -When Symfony's engine (called the ``Kernel``) boots up, it needs a map so +When Symfony's engine (called the 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 @@ -624,9 +647,8 @@ 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:: // web/app.php require_once __DIR__.'/../app/bootstrap.php'; @@ -637,55 +659,29 @@ 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. - -For a visual representation of how Symfony handles each request, see the -:ref:`request flow diagram `. - -.. _where-symfony2-delivers: +The front controller's only job is to initialize Symfony's engine (called the +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 +route is executed and your 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. -Where Symfony Delivers -~~~~~~~~~~~~~~~~~~~~~~ - -In the upcoming chapters, you'll learn more about how each piece of Symfony -works and the recommended organization of a project. For now, have a look -at how migrating the blog from flat PHP to Symfony has improved life: +It's a beautiful thing. -* Your application now has **clear and consistently organized code** (though - Symfony doesn't force you into this). This promotes **reusability** and - allows for new developers to be productive in your project more quickly; - -* 100% of the code you write is for *your* application. You **don't need - to develop or maintain low-level utilities** such as autoloading, - :doc:`routing `, or rendering :doc:`controllers `; - -* Symfony gives you **access to open source tools** such as Doctrine and the - Templating, Security, Form, Validation and Translation components (to name - a few); - -* The application now enjoys **fully-flexible URLs** thanks to the Routing - component; - -* Symfony's HTTP-centric architecture gives you access to powerful tools - such as **HTTP caching** powered by **Symfony's internal HTTP cache** or - more powerful tools such as `Varnish`_. This is covered in a later chapter - all about :doc:`caching `. - -And perhaps best of all, by using Symfony, you now have access to a whole -set of **high-quality open source tools developed by the Symfony community**! -A good selection of Symfony community tools can be found on `KnpBundles.com`_. +.. figure:: /images/request-flow.png + :align: center + :alt: Symfony request flow 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, rewriting ``list.html.php`` template in Twig would look like +this: .. code-block:: html+twig @@ -707,7 +703,7 @@ for example, the list template written in Twig: {% endblock %} -The corresponding ``layout.html.twig`` template is also easier to write: +And rewriting ``layout.html.php`` template in Twig would look like this: .. code-block:: html+twig @@ -726,18 +722,52 @@ Twig is well-supported in Symfony. And while PHP templates will always be supported in Symfony, the many advantages of Twig will continue to be discussed. For more information, see the :doc:`templating chapter `. +Where Symfony Delivers +---------------------- + +In the upcoming chapters, you'll learn more about how each piece of Symfony +works and how you can organize your project. For now, celebrate at how migrating +the blog from flat PHP to Symfony has improved life: + +* Your application now has **clear and consistently organized code** (though + Symfony doesn't force you into this). This promotes **reusability** and + allows for new developers to be productive in your project more quickly; + +* 100% of the code you write is for *your* application. You **don't need + to develop or maintain low-level utilities** such as autoloading, + :doc:`routing `, or rendering :doc:`controllers `; + +* Symfony gives you **access to open source tools** such as `Doctrine`_ and the + :doc:`Templating `, + :doc:`Security `, + :doc:`Form `, `Validator`_ and + :doc:`Translation ` components (to name + a few); + +* The application now enjoys **fully-flexible URLs** thanks to the Routing + component; + +* Symfony's HTTP-centric architecture gives you access to powerful tools + such as **HTTP caching** powered by **Symfony's internal HTTP cache** or + more powerful tools such as `Varnish`_. This is covered in a later chapter + all about :doc:`caching `. + +And perhaps best of all, by using Symfony, you now have access to a whole +set of **high-quality open source tools developed by the Symfony community**! +A good selection of Symfony community tools can be found on `KnpBundles.com`_. + Learn more from the Cookbook ---------------------------- * :doc:`/cookbook/templating/PHP` * :doc:`/cookbook/controller/service` +.. _`Model-View-Controller`: 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 +.. _`Validator`: https://github.com/symfony/validator .. _`Varnish`: https://www.varnish-cache.org/ -.. _`PHPUnit`: http://www.phpunit.de -.. _`Symfony distribution`: https://github.com/symfony/symfony-standard +.. _`KnpBundles.com`: http://knpbundles.com/ +.. _`Twig`: http://twig.sensiolabs.org \ No newline at end of file diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 86719d46251..ace570892fd 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -69,13 +69,14 @@ In HTTP-speak, this HTTP request would actually look something like this: This simple message communicates *everything* necessary about exactly which resource the client is requesting. The first line of an HTTP request is the -most important and contains two things: the URI and the HTTP method. +most important, because it contains two important things: the HTTP method (GET) +and the URL (``/``). The URI (e.g. ``/``, ``/contact``, etc) is the unique address or location that identifies the resource the client wants. The HTTP method (e.g. ``GET``) -defines what you want to *do* with the resource. The HTTP methods are the -*verbs* of the request and define the few common ways that you can act upon -the resource: +defines what the client wants to *do* with the resource. The HTTP methods (also +known as verbs) define the few common ways that the client can act upon the +resource - the most common HTTP methods are: +----------+---------------------------------------+ | *GET* | Retrieve the resource from the server | @@ -96,18 +97,18 @@ delete a specific blog entry, for example: .. note:: - There are actually nine HTTP methods (also known as verbs) defined by - the HTTP specification, but many of them are not widely used or supported. - In reality, many modern browsers only support ``POST`` and ``GET`` in - HTML forms. Various others are however supported in XMLHttpRequests, - as well as by Symfony's router. + There are actually nine HTTP methods defined by the HTTP specification, + but many of them are not widely used or supported. In reality, many + modern browsers only support ``POST`` and ``GET`` in HTML forms. Various + others are however supported in `XMLHttpRequest`_, as well as by Symfony's + :doc:`Routing component `. In addition to the first line, an HTTP request invariably contains other -lines of information called request headers. The headers can supply a wide -range of information such as the requested ``Host``, the response formats -the client accepts (``Accept``) and the application the client is using to -make the request (``User-Agent``). Many other headers exist and can be found -on Wikipedia's `List of HTTP header fields`_ article. +lines of information called request **headers**. The headers can supply a wide +range of information such as the host of the resource being requested (``Host``), +the response formats the client accepts (``Accept``) and the application the +client is using to make the request (``User-Agent``). Many other headers exist +and can be found on Wikipedia's `List of HTTP header fields`_ article. Step 2: The Server Returns a Response ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -138,18 +139,17 @@ like this: The HTTP response contains the requested resource (the HTML content in this case), as well as other information about the response. The first line is especially important and contains the HTTP response status code (200 in this -case). The status code communicates the overall outcome of the request back -to the client. Was the request successful? Was there an error? Different -status codes exist that indicate success, an error, or that the client needs -to do something (e.g. redirect to another page). A full list can be found -on Wikipedia's `List of HTTP status codes`_ article. +case). The status code communicates the overall outcome of the request back to the +client. Was the request successful? Was there an error? Different status codes exist +that indicate success, an error, or that the client needs to do something (e.g. +redirect to another page). A full list can be found on Wikipedia's `List of HTTP status codes`_ +article. Like the request, an HTTP response contains additional pieces of information -known as HTTP headers. For example, one important HTTP response header is -``Content-Type``. The body of the same resource could be returned in multiple +known as HTTP headers. The body of the same resource could be returned in multiple different formats like HTML, XML, or JSON and the ``Content-Type`` header uses Internet Media Types like ``text/html`` to tell the client which format is -being returned. You can see a `list of common media types`_ from IANA. +being returned. You can see a `List of common media types`_ from IANA. Many other headers exist, some of which are very powerful. For example, certain headers can be used to create a powerful caching system. @@ -196,7 +196,7 @@ from the HTTP request and using it to create an HTTP response. Instead of parsing the raw HTTP request message, PHP prepares superglobal variables such as ``$_SERVER`` and ``$_GET`` that contain all the information from the request. Similarly, instead of returning the HTTP-formatted text response, -you can use the ``header()`` function to create response headers and simply +you can use the PHP ``header()`` function to create response headers and simply print out the actual content that will be the content portion of the response message. PHP will create a true HTTP response and return it to the client: @@ -215,6 +215,10 @@ Requests and Responses in Symfony Symfony provides an alternative to the raw PHP approach via two classes that allow you to interact with the HTTP request and response in an easier way. + +Symfony Request Object +~~~~~~~~~~~~~~~~~~~~~~ + The :class:`Symfony\\Component\\HttpFoundation\\Request` class is a simple object-oriented representation of the HTTP request message. With it, you have all the request information at your fingertips:: @@ -226,17 +230,17 @@ have all the request information at your fingertips:: // the URI being requested (e.g. /about) minus any query parameters $request->getPathInfo(); - // retrieve GET and POST variables respectively + // retrieve $_GET and $_POST variables respectively $request->query->get('foo'); $request->request->get('bar', 'default value if bar does not exist'); - // retrieve SERVER variables + // retrieve $_SERVER variables $request->server->get('HTTP_HOST'); // retrieves an instance of UploadedFile identified by foo $request->files->get('foo'); - // retrieve a COOKIE value + // retrieve a $_COOKIE value $request->cookies->get('PHPSESSID'); // retrieve an HTTP request header, with normalized, lowercase keys @@ -273,9 +277,13 @@ the user is connecting via a secured connection (i.e. HTTPS). ``attributes`` property exists entirely to be a place where you can prepare and store context-specific information about the request. -Symfony also provides a ``Response`` class: a simple PHP representation of -an HTTP response message. This allows your application to use an object-oriented -interface to construct the response that needs to be returned to the client:: +Symfony Response Object +~~~~~~~~~~~~~~~~~~~~~~~ + +Symfony also provides a :class:`Symfony\\Component\\HttpFoundation\\Response` +class: a simple PHP representation of an HTTP response message. This allows your +application to use an object-oriented interface to construct the response that +needs to be returned to the client:: use Symfony\Component\HttpFoundation\Response; @@ -283,24 +291,35 @@ interface to construct the response that needs to be returned to the client:: $response->setContent('

Hello world!

'); $response->setStatusCode(Response::HTTP_OK); + + // set a HTTP response header $response->headers->set('Content-Type', 'text/html'); - // prints the HTTP headers followed by the content + // print the HTTP headers followed by the content $response->send(); +There are also special classes to make certain types of responses easier to create: + +* :ref:`JsonResponse `; + +* :ref:`BinaryFileResponse ` (for streaming + files and sending file downloads); + +* :ref:`StreamedResponse ` (for streaming any other large responses); + +.. tip:: + + The ``Request`` and ``Response`` classes are part of a standalone component + called :doc:`symfony/http-foundation ` + that yo can use in *any* PHP project. This also contains classes for handling + sessions, file uploads and more. + If Symfony offered nothing else, you would already have a toolkit for easily accessing request information and an object-oriented interface for creating the response. Even as you learn the many powerful features in Symfony, keep in mind that the goal of your application is always *to interpret a request and create the appropriate response based on your application logic*. -.. tip:: - - The ``Request`` and ``Response`` classes are part of a standalone component - included with Symfony called HttpFoundation. This component can be - used entirely independently of Symfony and also provides classes for handling - sessions and file uploads. - The Journey from the Request to the Response -------------------------------------------- @@ -316,6 +335,9 @@ code organized and maintainable? Symfony was created to solve these problems so that you don't have to. +.. index:: + single: Front controller; Origins + The Front Controller ~~~~~~~~~~~~~~~~~~~~ @@ -347,9 +369,8 @@ handles every request coming into your application. For example: .. tip:: - Using Apache's ``mod_rewrite`` (or equivalent with other web servers), - the URLs can easily be cleaned up to be just ``/``, ``/contact`` and - ``/blog``. + By using rewrite rules in your :doc:`web server configuration `, + the ``index.php`` won't be needed and you will have beautiful, clean URLs (e.g. ``/show``). Now, every request is handled exactly the same way. Instead of individual URLs executing different PHP files, the front controller is *always* executed, @@ -384,6 +405,9 @@ on that value. This can get ugly quickly:: Solving this problem can be difficult. Fortunately it's *exactly* what Symfony is designed to do. +.. index:: + single: HTTP; Symfony request flow + The Symfony Application Flow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -396,8 +420,8 @@ the same simple pattern for every request: :align: center :alt: Symfony request flow - Incoming requests are interpreted by the routing and passed to controller - functions that return ``Response`` objects. + Incoming requests are interpreted by the :doc:`Routing component ` and + passed to PHP functions that return ``Response`` objects. Each "page" of your site is defined in a routing configuration file that maps different URLs to different PHP functions. The job of each PHP function, @@ -408,13 +432,17 @@ you interpret the request and create a response. It's that easy! To review: -* Each request executes a front controller file; +* Each request executes the same, single file (called a "front controller"); + +* The front controller boots Symfony, and passes it request information; -* The routing system determines which PHP function should be executed based - on information from the request and routing configuration you've created; +* The router matches the incoming URL to a specific route and returns information + about the route, including the controller (i.e. function) that should be executed; -* The correct PHP function is executed, where your code creates and returns - the appropriate ``Response`` object. +* The controller (function) is executed: this is where *your* code creates and + returns the appropriate ``Response`` object; + +* The HTTP headers and content of the ``Response`` object are sent back to the client. A Symfony Request in Action ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -460,9 +488,10 @@ by adding an entry for ``/contact`` to your routing configuration file: return $collection; When someone visits the ``/contact`` page, this route is matched, and the -specified controller is executed. As you'll learn in the :doc:`routing chapter `, -the ``AppBundle:Main:contact`` string is a short syntax that points to a -specific PHP method ``contactAction`` inside a class called ``MainController``:: +specified controller is executed. As you'll learn in the +:ref:`routing chapter `, the ``AppBundle:Main:contact`` +string is a short syntax that points to a specific controller - ``contactAction()`` - +inside a controller class called - ``MainController``:: // src/AppBundle/Controller/MainController.php namespace AppBundle\Controller; @@ -477,9 +506,9 @@ specific PHP method ``contactAction`` inside a class called ``MainController``:: } } -In this very simple example, the controller simply creates a +In this example, the controller creates a :class:`Symfony\\Component\\HttpFoundation\\Response` object with the HTML -``

Contact us!

``. In the :doc:`controller chapter `, +``

Contact us!

``. In the :doc:`Controller chapter `, you'll learn how a controller can render templates, allowing your "presentation" code (i.e. anything that actually writes out HTML) to live in a separate template file. This frees up the controller to worry only about the hard @@ -504,7 +533,7 @@ tools. With Symfony, nothing is imposed on you: you're free to use the full Symfony Framework, or just one piece of Symfony all by itself. .. index:: - single: Symfony Components + single: Symfony Components .. _standalone-tools-the-symfony2-components: @@ -522,8 +551,8 @@ regardless of how your project is developed. To name a few: :doc:`Routing ` Powerful and fast routing system that allows you to map a specific URI - (e.g. ``/contact``) to some information about how that request should be handled - (e.g. execute the ``contactAction()`` method). + (e.g. ``/contact``) to information about how that request should be handled (e.g. + that the ``contactAction()`` controller method should be executed). :doc:`Form ` A full-featured and flexible framework for creating forms and handling form @@ -572,11 +601,12 @@ by using a Symfony distribution, which provides a project skeleton with sensible defaults. For more advanced users, the sky is the limit. .. _`xkcd`: http://xkcd.com/ +.. _`XMLHttpRequest`: https://en.wikipedia.org/wiki/XMLHttpRequest .. _`HTTP 1.1 RFC`: http://www.w3.org/Protocols/rfc2616/rfc2616.html .. _`HTTP Bis`: http://datatracker.ietf.org/wg/httpbis/ .. _`Live HTTP Headers`: https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/ -.. _`List of HTTP status codes`: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes .. _`List of HTTP header fields`: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields -.. _`list of common media types`: https://www.iana.org/assignments/media-types/media-types.xhtml +.. _`List of HTTP status codes`: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes +.. _`List of common media types`: https://www.iana.org/assignments/media-types/media-types.xhtml .. _`Validator`: https://github.com/symfony/validator .. _`Swift Mailer`: http://swiftmailer.org/ diff --git a/book/installation.rst b/book/installation.rst index e3db185d66f..93a7f9e51ab 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -1,5 +1,5 @@ .. index:: - single: Installation + single: Installing and Configuring Symfony Installing and Configuring Symfony ================================== @@ -69,7 +69,7 @@ with the ``new`` command: c:\> cd projects/ c:\projects\> php symfony new my_project_name -This command creates a new directory called ``my_project_name`` that contains a +This command creates a new directory called ``my_project_name/`` that contains a fresh new project based on the most recent stable Symfony version available. In addition, the installer checks if your system meets the technical requirements to execute Symfony applications. If not, you'll see the list of changes needed @@ -84,7 +84,7 @@ to meet those requirements. .. note:: If the installer doesn't work for you or doesn't output anything, make sure - that the `Phar extension`_ is installed and enabled on your computer. + that the PHP `Phar extension`_ is installed and enabled on your computer. Basing your Project on a Specific Symfony Version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -138,7 +138,7 @@ Start with :doc:`installing Composer globally `. Creating a Symfony Application with Composer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once Composer is installed on your computer, execute the ``create-project`` +Once Composer is installed on your computer, execute the ``create-project`` Composer command to create a new Symfony application based on its latest stable version: .. code-block:: bash @@ -146,7 +146,7 @@ command to create a new Symfony application based on its latest stable version: $ composer create-project symfony/framework-standard-edition my_project_name If you need to base your application on a specific Symfony version, provide that -version as the second argument of the ``create-project`` command: +version as the second argument of the ``create-project`` Composer command: .. code-block:: bash @@ -181,18 +181,14 @@ Instead of the Welcome Page, you may see a blank page or an error page. This is caused by a directory permission misconfiguration. There are several possible solutions depending on your operating system. All of them are explained in the :ref:`Setting up Permissions ` -section. +section of this chapter. -.. note:: +PHP's internal web server is great for developing, but should **not** be used on +production. Instead, use Apache or Nginx. See :doc:`/cookbook/configuration/web_server_configuration`. - PHP's internal web server is available in PHP 5.4 or higher versions. If you - still use the legacy PHP 5.3 version, you'll have to configure a *virtual host* - in your web server. +.. note:: -The ``server:run`` command is only suitable while developing the application. In -order to run Symfony applications on production servers, you'll have to configure -your `Apache`_ or `Nginx`_ web server as explained in -:doc:`/cookbook/configuration/web_server_configuration`. + PHP's internal web server is available in PHP 5.4 or higher versions. When you are finished working on your Symfony application, you can stop the server by pressing `Ctrl+C` from terminal. @@ -352,9 +348,9 @@ Symfony project packages "distributions", which are fully-functional application that include the Symfony core libraries, a selection of useful bundles, a sensible directory structure and some default configuration. In fact, when you created a Symfony application in the previous sections, you actually downloaded the -default distribution provided by Symfony, which is called *Symfony Standard Edition*. +default distribution provided by Symfony, which is called `Symfony Standard Edition`_. -The *Symfony Standard Edition* is by far the most popular distribution and it's +The Symfony Standard Edition is by far the most popular distribution and it's also the best choice for developers starting with Symfony. However, the Symfony Community has published other popular distributions that you may use in your applications: @@ -364,7 +360,7 @@ applications: developers to add CMS functionality to applications built with the Symfony Framework. * The `Symfony REST Edition`_ shows how to build an application that provides a - RESTful API using the FOSRestBundle and several other related bundles. + RESTful API using the `FOSRestBundle`_ and several other related bundles. Using Source Control -------------------- @@ -416,10 +412,8 @@ a wide variety of articles about solving specific problems with Symfony. .. _`explained in this post`: http://fabien.potencier.org/signing-project-releases.html .. _`Composer`: https://getcomposer.org/ -.. _`Composer download page`: https://getcomposer.org/download/ -.. _`Apache`: http://httpd.apache.org/docs/current/mod/core.html#documentroot -.. _`Nginx`: http://wiki.nginx.org/Symfony .. _`enable ACL support`: https://help.ubuntu.com/community/FilePermissionsACLs +.. _`Symfony Standard Edition`: https://github.com/symfony/symfony-standard .. _`Symfony CMF Standard Edition`: https://github.com/symfony-cmf/symfony-cmf-standard .. _`Symfony CMF`: http://cmf.symfony.com/ .. _`Symfony REST Edition`: https://github.com/gimler/symfony-rest-edition diff --git a/book/page_creation.rst b/book/page_creation.rst index ce3be3ce65b..0f1bb3067d2 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -1,5 +1,5 @@ .. index:: - single: Page creation + single: Create your First Page in Symfony .. _creating-pages-in-symfony2: .. _creating-pages-in-symfony: @@ -13,10 +13,13 @@ simple two-step process: #. *Create a route*: A route is the URL (e.g. ``/about``) to your page and points to a controller; -#. *Create a controller*: A controller is the function you write that builds - the page. You take the incoming request information and use it to create - a Symfony ``Response`` object, which can hold HTML content, a JSON string - or anything else. +#. *Create a controller*: A controller is the PHP function you write that + builds the page. You take the incoming request information and use it to + create a Symfony ``Response`` object, which can hold HTML content, a JSON + string or even a binary file like an image or PDF. The only rule is that + a controller *must* return a Symfony + :ref:`Response ` object (and you'll even + learn to bend this rule eventually). Just like on the web, every interaction is initiated by an HTTP request. Your job is pure and simple: understand that request and return a response. @@ -32,9 +35,10 @@ Creating a Page: Route and Controller Before continuing, make sure you've read the :doc:`Installation ` chapter and can access your new Symfony app in the browser. -Suppose you want to create a page - ``/lucky/number`` - that generates a -lucky (well, random) number and prints it. To do that, create a class and -a method inside of it that will be executed when someone goes to ``/lucky/number``:: +Suppose you want to create a page - ``/lucky/number`` - that generates a lucky (well, +random) number and prints it. To do that, create a "Controller class" and a +"controller" method inside of it that will be executed when someone goes to +``/lucky/number``:: // src/AppBundle/Controller/LuckyController.php namespace AppBundle\Controller; @@ -57,19 +61,19 @@ a method inside of it that will be executed when someone goes to ``/lucky/number } } -Before diving into this, test it out! +Before diving into this, test it out! If you are using PHP's internal web server +go to: http://localhost:8000/lucky/number -.. tip:: +If you set up a virtual host in Apache or Nginx replace ``http://localhost:8000`` +with your host name and add ``app_dev.php`` to make sure Symfony loads in the "dev" +environment: - If you set up a proper virtual host in - :doc:`Apache or Nginx `, - replace ``http://localhost:8000`` with your host name - like - ``http://symfony.dev/app_dev.php/lucky/number``. + http://symfony.dev/app_dev.php/lucky/number -If you see a lucky number being printed back to you, congratulations! But -before you run off to play the lottery, check out how this works. +If you see a lucky number being printed back to you, congratulations! But before +you run off to play the lottery, check out how this works. The ``@Route`` above ``numberAction()`` is called an *annotation* and it defines the URL pattern. You can also write routes in YAML (or other formats): @@ -119,7 +123,8 @@ Try this out in your browser: http://localhost:8000/api/lucky/number -You can even shorten this with the handy :class:`Symfony\\Component\\HttpFoundation\\JsonResponse`:: +You can even shorten this with the handy +:class:`Symfony\\Component\\HttpFoundation\\JsonResponse`:: // src/AppBundle/Controller/LuckyController.php // ... @@ -140,7 +145,7 @@ You can even shorten this with the handy :class:`Symfony\\Component\\HttpFoundat 'lucky_number' => rand(0, 100), ); - // calls json_encode and sets the Content-Type header + // calls json_encode() and sets the Content-Type header return new JsonResponse($data); } } @@ -207,7 +212,7 @@ at the end: return $collection; -Because of the ``{count}`` "placeholder", the URL to the page is *different*: +Because of the ``{count}`` "wildcard" placeholder, the URL to the page is *different*: it now works for URLs matching ``/lucky/number/*`` - for example ``/lucky/number/5``. The best part is that you can access this value and use it in your controller:: @@ -236,27 +241,25 @@ The best part is that you can access this value and use it in your controller:: // ... } -Try it by going to ``/lucky/number/XX`` - replacing XX with *any* number: +Try it by printing *7* lucky numbers: http://localhost:8000/lucky/number/7 -You should see *7* lucky numbers printed out! You can get the value of any -``{placeholder}`` in your route by adding a ``$placeholder`` argument to -your controller. Just make sure they have the same name. +**You can get the value of any ``{placeholder}`` in your route by adding +a ``$placeholder`` argument to your controller. Just make sure that the placeholder +(e.g. ``{id}``) matches the argument name (e.g. ``$id``).** The routing system can do a *lot* more, like supporting multiple placeholders (e.g. ``/blog/{category}/{page})``), making placeholders optional and forcing placeholder to match a regular expression (e.g. so that ``{count}`` *must* -be a number). - -Find out about all of this and become a routing expert in the +be a number). Find out about all of this and become a routing expert in the :doc:`Routing ` chapter. Rendering a Template (with the Service Container) ------------------------------------------------- If you're returning HTML from your controller, you'll probably want to render -a template. Fortunately, Symfony comes with Twig: a templating language that's +a template. Fortunately, Symfony comes with `Twig`_: a templating language that's easy, powerful and actually quite fun. So far, ``LuckyController`` doesn't extend any base class. The easiest way @@ -278,8 +281,8 @@ Using the ``templating`` Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This doesn't change anything, but it *does* give you access to Symfony's -:doc:`container `: an array-like object that gives -you access to *every* useful object in the system. These useful objects are +:doc:`service container `: an array-like object that +gives you access to *every* useful object in the system. These useful objects are called *services*, and Symfony ships with a service object that can render Twig templates, another that can log messages and many more. @@ -311,12 +314,15 @@ To render a Twig template, use a service called ``templating``:: You'll learn a lot more about the important "service container" as you keep reading. For now, you just need to know that it holds a lot of objects, and -you can ``get()`` any object by using its nickname, like ``templating`` or -``logger``. The ``templating`` service is an instance of :class:`Symfony\\Bundle\\TwigBundle\\TwigEngine` -and this has a ``render()`` method. +you can :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::get` +any object by using its nickname, like ``templating`` or ``logger``. +The ``templating`` service is an instance of +:class:`Symfony\\Bundle\\TwigBundle\\TwigEngine` and this has a +:method:`Symfony\\Bundle\\TwigBundle\\TwigEngine::render` method. But this can get even easier! By extending the ``Controller`` class, you -also get a lot of shortcut methods, like ``render()``:: +also get a lot of shortcut methods, like +:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render`:: // src/AppBundle/Controller/LuckyController.php // ... @@ -337,25 +343,20 @@ also get a lot of shortcut methods, like ``render()``:: return new Response($html); */ - // render: a shortcut that does the same as above + // render(): a shortcut that does the same as above return $this->render( 'lucky/number.html.twig', array('luckyNumberList' => $numbersList) ); } -Learn more about these shortcut methods and how they work in the +You will learn more about these shortcut methods and how they work in the :doc:`Controller ` chapter. -.. tip:: - - For more advanced users, you can also - :doc:`register your controllers as services `. - Create the Template ~~~~~~~~~~~~~~~~~~~ -If you refresh now, you'll get an error: +If you refresh your browser now, you'll get an error: Unable to find template "lucky/number.html.twig" @@ -382,23 +383,25 @@ a ``number.html.twig`` file inside of it:

Lucky Numbers: escape($luckyNumberList) ?> stop() ?> -Welcome to Twig! This simple file already shows off the basics: like how -the ``{{ variableName }}`` syntax is used to print something. The ``luckyNumberList`` -is a variable that you're passing into the template from the ``render`` call -in your controller. +Welcome to Twig! This simple file already shows off the basics: + +* The ``{{ variableName }}`` syntax is used to print something. In this template, + ``luckyNumberList`` is a variable that you're passing into the template from the + ``render`` call in the controller. -The ``{% extends 'base.html.twig' %}`` points to a layout file that lives -at `app/Resources/views/base.html.twig`_ and came with your new project. -It's *really* basic (an unstyled HTML structure) and it's yours to customize. -The ``{% block body %}`` part uses Twig's :ref:`inheritance system ` -to put the content into the middle of the ``base.html.twig`` layout. +* The ``{% extends 'base.html.twig' %}`` points to a layout file that lives + at `app/Resources/views/base.html.twig`_ and came with your new project. It's + *really* basic (an unstyled HTML structure) and it's yours to customize. + +* The ``{% block body %}`` part uses Twig's :ref:`inheritance system ` + to put the content into the middle of the ``base.html.twig`` layout. Refresh to see your template in action! - http://localhost:8000/lucky/number/9 + http://localhost:8000/lucky/number/7 -If you view the source code, you now have a basic HTML structure thanks to -``base.html.twig``. +If you view the source code of the displayed page, you now have a basic HTML +structure thanks to ``base.html.twig``. This is just the surface of Twig's power. When you're ready to master its syntax, loop over arrays, render other templates and other cool things, read @@ -440,13 +443,13 @@ see the :doc:`Bundles ` chapter. So what about the other directories in the project? ``vendor/`` - Vendor (i.e. third-party) libraries and bundles are downloaded here by - the `Composer`_ package manager. + Third-party (i.e. "vendor") libraries live here! These are typically downloaded + via the `Composer`_ package manager. ``web/`` This is the document root for the project and contains any publicly accessible - files, like CSS, images and the Symfony front controllers that execute - the app (``app_dev.php`` and ``app.php``). + files, like CSS, images and the Symfony development and production front controllers + that execute the app (``app_dev.php`` and ``app.php``). .. seealso:: @@ -542,7 +545,7 @@ use the handy ``app/console`` command: There's a lot more power behind Symfony's configuration system, including environments, imports and parameters. To learn all of it, see the -:doc:`Configuration ` chapter. +:doc:`Configuring Symfony (and Environments) ` chapter. What's Next? ------------ @@ -556,7 +559,8 @@ Ok, time to finish mastering the fundamentals by reading these chapters: * :doc:`/book/routing` * :doc:`/book/templating` -Then, in the :doc:`Symfony Book `, learn about the :doc:`service container `, +Then, in the :doc:`Symfony Book `, learn about the +:doc:`service container `, the :doc:`form system `, using :doc:`Doctrine ` (if you need to query a database) and more! @@ -565,6 +569,9 @@ There's also a :doc:`Cookbook ` *packed* with more advanced Have fun! +.. _`Symfony Standard Edition`: https://github.com/symfony/symfony-standard +.. _`Twig`: http://twig.sensiolabs.org .. _`app/Resources/views/base.html.twig`: https://github.com/symfony/symfony-standard/blob/2.7/app/Resources/views/base.html.twig +.. _`KnpBundles.com`: http://knpbundles.com .. _`Composer`: https://getcomposer.org .. _`find open source bundles`: http://knpbundles.com