diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 63243ef3a23..4dbf0a1b029 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 ``templates/list.php`` file, which is primarily an HTML file that uses a template-like PHP syntax: .. code-block:: html+php + @@ -122,7 +127,7 @@ is primarily an HTML file that uses a template-like PHP syntax: -By convention, the file that contains all the application logic - ``index.php`` - +By convention, the file that contains all the application logic is known as a "controller". The term :term:`controller` is a word you'll hear a lot, regardless of the language or framework you use. It refers simply to the area of *your* code that processes user input and prepares the response. @@ -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 ------------------------- @@ -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 + @@ -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 ``intval()`` PHP function, your +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 @@ -312,7 +322,7 @@ A "Front Controller" to the Rescue The solution is to use a :term:`front controller`: a single PHP file through which *all* requests are processed. With a front controller, the URIs for the -application change slightly, but start to become more flexible: +application change slightly, but start to become more flexible:: .. code-block:: text @@ -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:: + // 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 + 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,8 +414,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 @@ -405,7 +428,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. @@ -425,7 +448,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 @@ -433,7 +456,7 @@ into a vendor/ directory: Beside downloading your dependencies, Composer generates a ``vendor/autoload.php`` file, which takes care of autoloading for all the files in the Symfony Framework as well as -the files mentioned in the autoload section of your ``composer.json``. +the files mentioned in the ``autoload`` section of your ``composer.json``. Core to Symfony's philosophy is the idea that an application's main job is to interpret each request and return a response. To this end, Symfony provides @@ -499,7 +522,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()``. @@ -509,8 +533,6 @@ 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -518,8 +540,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:: @@ -557,10 +581,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. + The two controllers 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 @@ -583,7 +612,7 @@ database and the Templating component to render a template and return a -The layout is nearly identical: +The layout ``layout.php`` is nearly identical: .. code-block:: html+php @@ -603,12 +632,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 +652,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,55 +665,27 @@ 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: - -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: - -* 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); +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 +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. -* The application now enjoys **fully-flexible URLs** thanks to the Routing - component; +.. figure:: /images/request-flow.png + :align: center + :alt: Symfony request flow -* 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`_. - -Better Templates ----------------- +PHP Templates versus Twig 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 @@ -705,7 +707,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 @@ -722,7 +724,42 @@ The corresponding ``layout.html.twig`` template is also easier to write: 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 `. +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 the recommended organization of a project. For now, have a look +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 ---------------------------- @@ -730,12 +767,14 @@ 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/ +.. _`Symfony distribution`: https://github.com/symfony/symfony-standard .. _`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/ \ No newline at end of file diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 8f8da7213cc..267c3408ac4 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -1,5 +1,5 @@ .. index:: - single: Symfony Fundamentals + single: HTTP Fundamentals .. _symfony2-and-http-fundamentals: @@ -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 and contains three things: the HTTP method, the requested URI +and HTTP protocol version being used. 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 acts upon the +resource: +----------+---------------------------------------+ | *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. +In addition to the first line, a HTTP request invariably contains other +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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -137,19 +138,18 @@ 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. +especially important. Beside HTTP protocol version it 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. 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. @@ -176,7 +176,7 @@ Symfony is architected to match this reality. while browsing is the `Live HTTP Headers`_ extension for Firefox. .. index:: - single: Symfony Fundamentals; Requests and responses + single: HTTP; HTTP in PHP Requests and Responses in PHP ----------------------------- @@ -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: @@ -210,8 +210,14 @@ message. PHP will create a true HTTP response and return it to the client: The URI requested is: /testing?foo=symfony The value of the "foo" parameter is: symfony -Requests and Responses in Symfony ---------------------------------- +.. index:: + single: HTTP; HTTP in Symfony + single: HTTP; Symfony Request object + +.. _book-request-object: + +Symfony Request Object +---------------------- 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. @@ -246,36 +252,50 @@ have all the request information at your fingertips:: $request->getMethod(); // GET, POST, PUT, DELETE, HEAD $request->getLanguages(); // an array of languages the client accepts +``Request`` class has several public properties via which we can access information +about the client request. As seen above, the ``$_GET`` and ``$_POST`` PHP global +variables are accessible via the public ``query`` and ``request`` properties +respectively, ``$_COOKIE`` is accessible via ``cookies`` property, ``$_FILES`` +via ``files`` property and ``$_SERVER`` via ``server`` property. ``headers`` +property is mostly equivalent to a subset of ``$_SERVER`` +(e.g. $request->headers->get('User-Agent')). Each property is a +:class:`Symfony\\Component\\HttpFoundation\\ParameterBag` instance (or a sub-class +of: :class:`Symfony\\Component\\HttpFoundation\\ServerBag`, +:class:`Symfony\\Component\\HttpFoundation\\FileBag`, +:class:`Symfony\\Component\\HttpFoundation\\HeaderBag` +), which is a data holder class. All ``ParameterBag`` instances have methods to +retrieve and update their data like: ``get()`` to return a parameter by name, +``has()`` to return true if the parameter is defined, ``all()`` to return all +the parameters and many more. + +.. _book-fundamentals-attributes: + +The ``Request`` class also has a public ``attributes`` property, which holds +special data related to how the application works internally. For the +Symfony Framework, the ``attributes`` holds the values returned by the +matched route, like ``_controller``, ``id`` (if you have an ``{id}`` +"wildcard" placeholders), and even the name of the matched route (``_route``) +(you will learn about these route parameters and controller arguments in +:ref:`routing chapter `). The ``attributes`` +property exists entirely to be a place where you can prepare and store +context-specific information about the request. + As a bonus, the ``Request`` class does a lot of work in the background that -you'll never need to worry about. For example, the ``isSecure()`` method +you'll never need to worry about. For example, the +:method:`Symfony\\Component\\HttpFoundation\\Request::isSecure` method checks the *three* different values in PHP that can indicate whether or not the user is connecting via a secured connection (i.e. HTTPS). -.. sidebar:: ParameterBags and Request Attributes - - As seen above, the ``$_GET`` and ``$_POST`` variables are accessible via - the public ``query`` and ``request`` properties respectively. Each of - these objects is a :class:`Symfony\\Component\\HttpFoundation\\ParameterBag` - object, which has methods like - :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::get`, - :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::has`, - :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::all` and more. - In fact, every public property used in the previous example is some instance - of the ParameterBag. - - .. _book-fundamentals-attributes: +.. index:: + single: HTTP; Symfony Respond object - The Request class also has a public ``attributes`` property, which holds - special data related to how the application works internally. For the - Symfony Framework, the ``attributes`` holds the values returned by the - matched route, like ``_controller``, ``id`` (if you have an ``{id}`` - wildcard), and even the name of the matched route (``_route``). The - ``attributes`` property exists entirely to be a place where you can - prepare and store context-specific information about the request. +Symfony Response Object +----------------------- -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 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 +303,46 @@ interface to construct the response that needs to be returned to the client:: $response->setContent('

Hello world!

'); $response->setStatusCode(200); + + // 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(); +Like the ``Request``, the ``Response`` also has a public ``headers`` property +which is a :class:`Symfony\\Component\\HttpFoundation\\ResponseHeaderBag` instance. +``ResponseHeaderBag`` instances have methods for getting and setting the response +headers. The header names are normalized so that using ``Content-Type`` is equivalent +to ``content-type`` or even ``content_type``. + +There are also special classes to make certain kinds of responses easier: + +* For JSON, there is :class:`Symfony\\Component\\HttpFoundation\\JsonResponse`. + See :ref:`component-http-foundation-json-response`. + +* For files, there is :class:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse`. + See :ref:`component-http-foundation-serving-files`. + +* For streamed responses, there is + :class:`Symfony\\Component\\HttpFoundation\\StreamedResponse`. + See :ref:`streaming-response`. + +.. 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. So, now that you know the basics you can continue your research + on Symfony ``Request`` and ``Response`` object in the + :ref:`HttpFoundation component documentation `. + 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 +358,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 ~~~~~~~~~~~~~~~~~~~~ @@ -348,8 +393,8 @@ file that 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``. + the URL can easily be cleaned up - ``index.php`` portion removed - + to be just ``/``, ``/contact`` and ``/blog``. Now, every request is handled exactly the same way. Instead of individual URLs executing different PHP files, the front controller is *always* executed, @@ -384,44 +429,63 @@ 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When you let Symfony handle each request, life is much easier. Symfony follows the same simple pattern for every request: -.. _request-flow-figure: - .. figure:: /images/request-flow.png :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, -called a :term:`controller`, is to use information from the request - along +called a :term:`controller`, is to use information from the ``Request`` object - along with many other tools Symfony makes available - to create and return a ``Response`` object. In other words, the controller is where *your* code goes: it's where you interpret the request and create a response. It's that easy! To review: -* Each request executes a front controller file; +* Each request executes a single front controller file; + +* 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 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 that should be executed; -* The correct PHP function is executed, where your code creates and returns - the appropriate ``Response`` object. +* The correct controller from the matched 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. + +.. note:: + + Though similarly named, a "front controller" is different from the PHP functions + called "controllers" talked about in this chapter. A front controller is a short PHP + file through which all requests are directed. A typical application will have a + production front controller and a development front controller. The "controller + class" is a convenient way to group several "controllers" together in one class. + So a controller is a method inside a controller class. They hold your code which + creates and returns the appropriate ``Response`` object. Controllers are also called + *actions*. A Symfony Request in Action ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Without diving into too much detail, here is this process in action. Suppose you want to add a ``/contact`` page to your Symfony application. First, start -by adding an entry for ``/contact`` to your routing configuration file: +by adding an entry for ``/contact`` to your routing configuration file:: .. configuration-block:: @@ -460,9 +524,15 @@ 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 named *logical controller name* that points to a specific +controller ``contactAction()`` inside a controller class called ``MainController``. +In the routing chapter you will also learn about routing parameters like +``_controller``, ``_route`` and the ``defaults`` array. + +In the following very simple example, the controller simply creates a ``Response`` +object with the HTML ``

Contact us!

``:: // src/AppBundle/Controller/MainController.php namespace AppBundle\Controller; @@ -477,14 +547,11 @@ specific PHP method ``contactAction`` inside a class called ``MainController``:: } } -In this very simple example, the controller simply creates a -:class:`Symfony\\Component\\HttpFoundation\\Response` object with the HTML -``

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 -stuff: interacting with the database, handling submitted data, or sending -email messages. +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 stuff: interacting with the database, handling +submitted data, or sending email messages. .. _symfony2-build-your-app-not-your-tools: @@ -504,9 +571,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 - -.. _standalone-tools-the-symfony2-components: + single: Symfony; Components Standalone Tools: The Symfony *Components* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -522,8 +587,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 some information about how that request should be handled; + which controller should be executed (e.g. execute the ``contactAction()`` method). :doc:`Form ` A full-featured and flexible framework for creating forms and handling form @@ -547,7 +612,8 @@ Each one of these components is decoupled and can be used in *any* PHP project, regardless of whether or not you use the Symfony Framework. Every part is made to be used if needed and replaced when necessary. -.. _the-full-solution-the-symfony2-framework: +.. index:: + single: Symfony; Framework The Full Solution: The Symfony *Framework* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -563,7 +629,7 @@ a PHP library that accomplishes two distinct tasks: The goal of the framework is to integrate many independent tools in order to provide a consistent experience for the developer. Even the framework -itself is a Symfony bundle (i.e. a plugin) that can be configured or replaced +itself is a Symfony :term:`bundle` (i.e. a plugin) that can be configured or replaced entirely. Symfony provides a powerful set of tools for rapidly developing web applications @@ -572,11 +638,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 +.. _`List of HTTP header fields`: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields +.. _`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 .. _`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 .. _`Validator`: https://github.com/symfony/validator .. _`Swift Mailer`: http://swiftmailer.org/ diff --git a/book/installation.rst b/book/installation.rst index 2976d4ec4e7..3123f9721e2 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 ================================== @@ -28,7 +28,7 @@ ways. Linux and Mac OS X Systems ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Open your command console and execute the following commands: +Open your command console and execute the following commands:: .. code-block:: bash @@ -40,14 +40,14 @@ This will create a global ``symfony`` command in your system. Windows Systems ~~~~~~~~~~~~~~~ -Open your command console and execute the following command: +Open your command console and execute the following command:: .. code-block:: bash c:\> php -r "readfile('https://symfony.com/installer');" > symfony Then, move the downloaded ``symfony`` file to your project's directory and -execute it as follows: +execute it as follows:: .. code-block:: bash @@ -58,7 +58,7 @@ Creating the Symfony Application -------------------------------- Once the Symfony Installer is available, create your first Symfony application -with the ``new`` command: +with the ``new`` command:: .. code-block:: bash @@ -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,13 +84,13 @@ 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In case your project needs to be based on a specific Symfony version, use the -optional second argument of the ``new`` command: +optional second argument of the ``new`` command:: .. code-block:: bash @@ -108,7 +108,7 @@ optional second argument of the ``new`` command: $ symfony new my_project 2.7.0-RC1 The installer also supports a special version called ``lts`` which installs the -most recent :ref:`Symfony LTS version ` available: +most recent :ref:`Symfony LTS version ` available:: .. code-block:: bash @@ -139,15 +139,15 @@ Start with :doc:`installing Composer globally `. Creating a Symfony Application with Composer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once Composer is installed on your computer, execute the ``create-project`` -command to create a new Symfony application based on its latest stable version: +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 $ 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 @@ -159,12 +159,14 @@ version as the second argument of the ``create-project`` command: doing anything. If that's your case, add the ``-vvv`` flag to the previous command to display a detailed output of everything that Composer is doing. + $ composer create-project -vvv symfony/framework-standard-edition my_project_name "2.3.*" + Running the Symfony Application ------------------------------- Symfony leverages the internal web server provided by PHP to run applications while developing them. Therefore, running a Symfony application is a matter of -browsing the project directory and executing this command: +browsing the project directory and executing this command:: .. code-block:: bash @@ -182,21 +184,21 @@ 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:: +Using PHP's internal web server 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 and virtual host as explained in +cookbook article :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. So, if you + still use the legacy PHP 5.3 version, you'll also have to configure `Apache`_ or + `Nginx`_ web server and virtual host. When you are finished working on your Symfony application, you can stop the -server with the ``server:stop`` command: +server with the ``server:stop`` command:: .. code-block:: bash @@ -207,7 +209,7 @@ Checking Symfony Application Configuration and Setup Symfony applications come with a visual server configuration tester to show if your environment is ready to use Symfony. Access the following URL to check your -configuration: +configuration:: .. code-block:: text @@ -217,70 +219,71 @@ If there are any issues, correct them now before moving on. .. _book-installation-permissions: -.. sidebar:: Setting up Permissions +Setting up Permissions +~~~~~~~~~~~~~~~~~~~~~~ - One common issue when installing Symfony is that the ``app/cache`` and - ``app/logs`` directories must be writable both by the web server and the - command line user. On a UNIX system, if your web server user is different - from your command line user, you can try one of the following solutions. +One common issue when installing Symfony is that the **``app/cache`` and +``app/logs`` directories must be writable both by the web server and the +command line user**. On a UNIX system, if your web server user is different +from your command line user, you can try one of the following solutions. - **1. Use the same user for the CLI and the web server** +**1. Use the same user for the CLI and the web server** - In development environments, it is a common practice to use the same UNIX - user for the CLI and the web server because it avoids any of these permissions - issues when setting up new projects. This can be done by editing your web server - configuration (e.g. commonly httpd.conf or apache2.conf for Apache) and setting - its user to be the same as your CLI user (e.g. for Apache, update the ``User`` - and ``Group`` values). +In development environments, it is a common practice to use the same UNIX +user for the CLI and the web server because it avoids any of these permissions +issues when setting up new projects. This can be done by editing your web server +configuration (e.g. commonly ``httpd.conf`` or ``apache2.conf`` for Apache) and setting +its user to be the same as your CLI user (e.g. for Apache, update the ``User`` +and ``Group`` values). - **2. Using ACL on a system that supports chmod +a** +**2. Using ACL on a system that supports chmod +a** - Many systems allow you to use the ``chmod +a`` command. Try this first, - and if you get an error - try the next method. This uses a command to - try to determine your web server user and set it as ``HTTPDUSER``: +Many systems allow you to use the ``chmod +a`` command. Try this first, +and if you get an error - try the next method. This uses a command to +try to determine your web server user and set it as ``HTTPDUSER``:: - .. code-block:: bash +.. code-block:: bash - $ rm -rf app/cache/* - $ rm -rf app/logs/* + $ rm -rf app/cache/* + $ rm -rf app/logs/* - $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` - $ sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs - $ sudo chmod +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs + $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` + $ sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs + $ sudo chmod +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs - **3. Using ACL on a system that does not support chmod +a** +**3. Using ACL on a system that does not support chmod +a** - Some systems don't support ``chmod +a``, but do support another utility - called ``setfacl``. You may need to `enable ACL support`_ on your partition - and install setfacl before using it (as is the case with Ubuntu). This - uses a command to try to determine your web server user and set it as - ``HTTPDUSER``: +Some systems don't support ``chmod +a``, but do support another utility +called ``setfacl``. You may need to `enable ACL support`_ on your partition +and install ``setfacl`` before using it (as is the case with Ubuntu). This +uses a command to try to determine your web server user and set it as +``HTTPDUSER``:: - .. code-block:: bash +.. code-block:: bash - $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` - $ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs - $ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs + $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` + $ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs + $ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs - If this doesn't work, try adding ``-n`` option. +If this doesn't work, try adding ``-n`` option. - **4. Without using ACL** +**4. Without using ACL** - If none of the previous methods work for you, change the umask so that the - cache and log directories will be group-writable or world-writable (depending - if the web server user and the command line user are in the same group or not). - To achieve this, put the following line at the beginning of the ``app/console``, - ``web/app.php`` and ``web/app_dev.php`` files:: +If none of the previous methods work for you, change the umask so that the +cache and log directories will be group-writable or world-writable (depending +if the web server user and the command line user are in the same group or not). +To achieve this, put the following line at the beginning of the ``app/console``, +``web/app.php`` and ``web/app_dev.php`` files:: - umask(0002); // This will let the permissions be 0775 + umask(0002); // This will let the permissions be 0775 - // or + // or - umask(0000); // This will let the permissions be 0777 + umask(0000); // This will let the permissions be 0777 - Note that using the ACL is recommended when you have access to them - on your server because changing the umask is not thread-safe. +Note that using the ACL is recommended when you have access to them +on your server because changing the umask is not thread-safe. .. _installation-updating-vendors: @@ -294,7 +297,7 @@ and they are managed exclusively by Composer. Updating those third-party libraries frequently is a good practice to prevent bugs and security vulnerabilities. Execute the ``update`` Composer command to update -them all at once: +them all at once:: .. code-block:: bash @@ -304,6 +307,39 @@ them all at once: Depending on the complexity of your project, this update process can take up to several minutes to complete. +Using Source Control +-------------------- + +If you're using a version control system like `Git`_, you can safely commit all +your project's code. The reason is that Symfony applications already contain a +``.gitignore`` file specially prepared for Symfony. + +For specific instructions on how best to set up your project to be stored +in Git, see cookbook article :doc:`/cookbook/workflow/new_project_git`. + +Checking out a Versioned Symfony Application +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using Composer to manage application's dependencies, it's recommended to +ignore the entire ``vendor/`` directory before committing its code to the +repository. This means that when checking out a Symfony application from a Git +repository, there will be no ``vendor/`` directory and the application won't +work out-of-the-box. + +In order to make it work, check out the Symfony application and then execute the +``install`` Composer command to download and install all the dependencies required +by the application:: + +.. code-block:: bash + + $ cd my_project_name/ + $ composer install + +How does Composer know which specific dependencies to install? Because when a +Symfony application is committed to a repository, the ``composer.json`` and +``composer.lock`` files are also committed. These files tell Composer which +dependencies (and which specific versions) to install for the application. + Installing the Symfony Demo Application --------------------------------------- @@ -313,7 +349,7 @@ conceived as a learning tool for Symfony newcomers and its source code contains tons of comments and helpful notes. In order to download the Symfony Demo application, execute the ``demo`` command -of the Symfony Installer anywhere in your system: +of the Symfony Installer anywhere in your system:: .. code-block:: bash @@ -337,52 +373,34 @@ 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: * The `Symfony CMF Standard Edition`_ is the best distribution to get started with the `Symfony CMF`_ project, which is a project that makes it easier for - developers to add CMS functionality to applications built with the Symfony + 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. - -Using Source Control --------------------- - -If you're using a version control system like `Git`_, you can safely commit all -your project's code. The reason is that Symfony applications already contain a -``.gitignore`` file specially prepared for Symfony. - -For specific instructions on how best to set up your project to be stored -in Git, see :doc:`/cookbook/workflow/new_project_git`. - -Checking out a versioned Symfony Application -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + RESTful API using the `FOSRestBundle`_ and several other related bundles. -When using Composer to manage application's dependencies, it's recommended to -ignore the entire ``vendor/`` directory before committing its code to the -repository. This means that when checking out a Symfony application from a Git -repository, there will be no ``vendor/`` directory and the application won't -work out-of-the-box. +Configuration Formats +--------------------- -In order to make it work, check out the Symfony application and then execute the -``install`` Composer command to download and install all the dependencies required -by the application: +Symfony supports several configuration formats: YAML, XML and PHP. Throughout +the chapters, all configuration examples will be shown in all three formats. +Each has its own advantages and disadvantages. The choice of which to use is up +to you: -.. code-block:: bash +* *YAML*: Simple, clean and readable (learn more about YAML in the Yaml component + documentation :doc:`/components/yaml/yaml_format`); - $ cd my_project_name/ - $ composer install +* *XML*: More powerful than YAML at times and supports IDE autocompletion; -How does Composer know which specific dependencies to install? Because when a -Symfony application is committed to a repository, the ``composer.json`` and -``composer.lock`` files are also committed. These files tell Composer which -dependencies (and which specific versions) to install for the application. +* *PHP*: Very powerful but less readable than standard configuration formats. Beginning Development --------------------- @@ -400,14 +418,15 @@ Be sure to also check out the :doc:`Cookbook `, which contains a wide variety of articles about solving specific problems with Symfony. .. _`explained in this post`: http://fabien.potencier.org/signing-project-releases.html +.. _`Phar extension`: http://php.net/manual/en/intro.phar.php .. _`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 +.. _`Git`: http://git-scm.com/ +.. _`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/ +.. _`CMS`: https://en.wikipedia.org/wiki/Content_management_system .. _`Symfony REST Edition`: https://github.com/gimler/symfony-rest-edition .. _`FOSRestBundle`: https://github.com/FriendsOfSymfony/FOSRestBundle -.. _`Git`: http://git-scm.com/ -.. _`Phar extension`: http://php.net/manual/en/intro.phar.php diff --git a/book/page_creation.rst b/book/page_creation.rst index ce3be3ce65b..51636fef794 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,73 +13,128 @@ 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 :term:`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. -.. index:: - single: Page creation; Example - Creating a Page: Route and Controller ------------------------------------- .. tip:: - Before continuing, make sure you've read the :doc:`Installation ` - chapter and can access your new Symfony app in the browser. + Before continuing, make sure you've read the + :doc:`Installation ` chapter, installed + `Symfony Standard Edition`_ and can access your new Symfony app in the + browser either using PHP's internal web server or by setting proper + virtual host in Apache or Nginx. -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``:: + Using PHP's internal web server 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 and virtual + host as explained in :doc:`/cookbook/configuration/web_server_configuration`. - // src/AppBundle/Controller/LuckyController.php - namespace AppBundle\Controller; +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``:: - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; - use Symfony\Component\HttpFoundation\Response; +.. configuration-block:: - class LuckyController - { - /** - * @Route("/lucky/number") - */ - public function numberAction() + .. code-block:: php-annotations + + // src/AppBundle/Controller/LuckyController.php + namespace AppBundle\Controller; + + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + use Symfony\Component\HttpFoundation\Response; + + class LuckyController { - $number = rand(0, 100); + /** + * @Route("/lucky/number") + */ + public function numberAction() + { + $number = rand(0, 100); - return new Response( - 'Lucky number: '.$number.'' - ); + return new Response( + 'Lucky number: '.$number.'' + ); + } } - } -Before diving into this, test it out! + .. code-block:: yaml + + # app/config/routing.yml + lucky_number: + path: /lucky/number + defaults: { _controller: AppBundle:Lucky:number } + + .. code-block:: xml + + + + + + + AppBundle:Lucky:number + + + + .. code-block:: php + + // app/config/routing.php + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + $collection->add('lucky_number', new Route('/lucky/number', array( + '_controller' => 'AppBundle:Lucky:number', + ))); + + return $collection; + +"Controller class" is a convenient way to group several "controllers" together. + +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 proper virtual host in Apache or Nginx replace ``http://localhost:8000`` +with your host name and add the name of the development front controller file you +are using ``web/app_dev.php``: + + http://symfony.dev/app_dev.php/lucky/number - 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``. +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()`` method is called an :term:`annotation` +and defines the route so that :doc:`Router ` can match the incoming URL +(``http://localhost:8000/lucky/number``) to a specific route (``/lucky/number``) +and therefore returns information about the route, including the controller method +that should be executed. The correct controller from the matched route is executed +and the code inside the controller creates and returns the appropriate ``Response`` +object. -The ``@Route`` above ``numberAction()`` is called an *annotation* and it -defines the URL pattern. You can also write routes in YAML (or other formats): -read about this in the :doc:`routing ` chapter. Actually, most -routing examples in the docs have tabs that show you how each format looks. +.. note:: -The method below the annotation - ``numberAction`` - is called the *controller* -and is where you build the page. The only rule is that a controller *must* -return a Symfony :ref:`Response ` object -(and you'll even learn to bend this rule eventually). + You can also write routes in YAML, XML or PHP: you will learn about + this in the :doc:`Routing ` chapter. If you look closer + the above example has tabs that show you how each format looks - all three additional + formats use routing configuration file to define routes. Actually, most + routing examples in the docs have tabs that show you how each format looks. Creating a JSON Response ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -119,7 +174,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 +196,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); } } @@ -150,8 +206,8 @@ Dynamic URL Patterns: /lucky/number/{count} Woh, you're doing great! But Symfony's routing can do a lot more. Suppose now that you want a user to be able to go to ``/lucky/number/5`` to generate -*5* lucky numbers at once. Update the route to have a ``{wildcard}`` part -at the end: +*5* lucky numbers at once. Update the route to have a "wildcard" placeholders +``{counter}`` at the end:: .. configuration-block:: @@ -207,7 +263,7 @@ at the end: return $collection; -Because of the ``{count}`` "placeholder", the URL to the page is *different*: +Because of the ``{count}`` "wildcard" placeholders, 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 +292,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 they have +the same name.** 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 +332,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 +365,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,30 +394,25 @@ 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" Fix that by creating a new ``app/Resources/views/lucky`` directory and putting -a ``number.html.twig`` file inside of it: +a ``number.html.twig`` file inside of it:: .. configuration-block:: @@ -382,23 +434,26 @@ 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 ``{% 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. +* ``{{ variableName }}`` syntax is used to print a variable that you're + passing into the template from the array list in ``render()`` method in your + 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 + Symfony Standard Edition. 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 @@ -429,36 +484,39 @@ The ``app/`` directory also holds a few other things, like the cache directory which you'll use to enable new bundles (and one of a *very* short list of PHP files in ``app/``). -The ``src/`` directory has just one directory - ``src/AppBundle`` - -and everything lives inside of it. A bundle is like a "plugin" and you can -`find open source bundles`_ and install them into your project. But even -*your* code lives in a bundle - typically ``AppBundle`` (though there's -nothing special about ``AppBundle``). To find out more about bundles and -why you might create multiple bundles (hint: sharing code between projects), -see the :doc:`Bundles ` chapter. +The ``src/`` directory has just one directory ``src/AppBundle`` and everything +lives inside of it. Is where your code lives. It's a set of files within a +directory that implement a single feature. Symfony Standard Edition comes with +``AppBundle`` but there is nothing special about ``AppBundle``. Your project can +have as many bundles as you want, you can even use third-party bundles written +by other that you can find at `KnpBundles.com`_. So, a :term:`bundle` is like a +"plugin" in other software, but even better. To find out more about bundles and +why you might create multiple bundles (hint: sharing code between projects), 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. + Location to which vendor (i.e. third-party) libraries and bundles are + downloaded by 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:: Symfony is flexible. If you need to, you can easily override the default - directory structure. See :doc:`/cookbook/configuration/override_dir_structure`. + directory structure. See cookbook article + :doc:`/cookbook/configuration/override_dir_structure`. Application Configuration ------------------------- -Symfony comes with several built-in bundles (open your ``app/AppKernel.php`` -file) and you'll probably install more. The main configuration file for bundles -is ``app/config/config.yml``: +Symfony Standard Edition comes with several built-in bundles (open your +``app/AppKernel.php`` file) and you'll probably install more. The main configuration +file for bundles is ``app/config/config.yml``:: .. configuration-block:: @@ -528,8 +586,8 @@ is ``app/config/config.yml``: // ... -The ``framework`` key configures FrameworkBundle, the ``twig`` key configures -TwigBundle and so on. A *lot* of behavior in Symfony can be controlled just +The ``framework`` key configures ``FrameworkBundle``, the ``twig`` key configures +``TwigBundle`` and so on. A *lot* of behavior in Symfony can be controlled just by changing one option in this configuration file. To find out how, see the :doc:`Configuration Reference ` section. @@ -542,7 +600,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 +614,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 +624,8 @@ 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 -.. _`Composer`: https://getcomposer.org -.. _`find open source bundles`: http://knpbundles.com +.. _`KnpBundles.com`: http://knpbundles.com +.. _`Composer`: https://getcomposer.org \ No newline at end of file diff --git a/book/routing.rst b/book/routing.rst index 56854ea337b..89557ad66cc 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -1050,6 +1050,8 @@ a slash. URLs matching this route might look like: Symfony provides you with a way to do this by leveraging service container parameters. Read more about this in ":doc:`/cookbook/routing/service_container_parameters`". +.. book-special-routing-parameters: + Special Routing Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~