diff --git a/book/bundles.rst b/book/bundles.rst new file mode 100644 index 00000000000..ff09cc6fc3e --- /dev/null +++ b/book/bundles.rst @@ -0,0 +1,175 @@ +.. index:: + single: Bundles + +.. _page-creation-bundles: + +The Bundle System +================= + +A bundle is similar to a plugin in other software, but even better. The key +difference is that *everything* is a bundle in Symfony, including both the +core framework functionality and the code written for your application. +Bundles are first-class citizens in Symfony. This gives you the flexibility +to use pre-built features packaged in `third-party bundles`_ or to distribute +your own bundles. It makes it easy to pick and choose which features to enable +in your application and to optimize them the way you want. + +.. note:: + + While you'll learn the basics here, an entire cookbook entry is devoted + to the organization and best practices of :doc:`bundles `. + +A bundle is simply a structured set of files within a directory that implement +a single feature. You might create a BlogBundle, a ForumBundle or +a bundle for user management (many of these exist already as open source +bundles). Each directory contains everything related to that feature, including +PHP files, templates, stylesheets, JavaScript files, tests and anything else. +Every aspect of a feature exists in a bundle and every feature lives in a +bundle. + +Bundles used in your applications must be enabled by registering them in +the ``registerBundles()`` method of the ``AppKernel`` class:: + + // app/AppKernel.php + public function registerBundles() + { + $bundles = array( + new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), + new Symfony\Bundle\SecurityBundle\SecurityBundle(), + new Symfony\Bundle\TwigBundle\TwigBundle(), + new Symfony\Bundle\MonologBundle\MonologBundle(), + new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), + new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), + new Symfony\Bundle\AsseticBundle\AsseticBundle(), + new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), + new AppBundle\AppBundle(), + ); + + if (in_array($this->getEnvironment(), array('dev', 'test'))) { + $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); + $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); + $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); + } + + return $bundles; + } + +With the ``registerBundles()`` method, you have total control over which bundles +are used by your application (including the core Symfony bundles). + +.. tip:: + + A bundle can live *anywhere* as long as it can be autoloaded (via the + autoloader configured at ``app/autoload.php``). + +Creating a Bundle +----------------- + +The Symfony Standard Edition comes with a handy task that creates a fully-functional +bundle for you. Of course, creating a bundle by hand is pretty easy as well. + +To show you how simple the bundle system is, create a new bundle called +AcmeTestBundle and enable it. + +.. tip:: + + The ``Acme`` portion is just a dummy name that should be replaced by + some "vendor" name that represents you or your organization (e.g. + ABCTestBundle for some company named ``ABC``). + +Start by creating a ``src/Acme/TestBundle/`` directory and adding a new file +called ``AcmeTestBundle.php``:: + + // src/Acme/TestBundle/AcmeTestBundle.php + namespace Acme\TestBundle; + + use Symfony\Component\HttpKernel\Bundle\Bundle; + + class AcmeTestBundle extends Bundle + { + } + +.. tip:: + + The name AcmeTestBundle follows the standard + :ref:`Bundle naming conventions `. You could + also choose to shorten the name of the bundle to simply TestBundle by naming + this class TestBundle (and naming the file ``TestBundle.php``). + +This empty class is the only piece you need to create the new bundle. Though +commonly empty, this class is powerful and can be used to customize the behavior +of the bundle. + +Now that you've created the bundle, enable it via the ``AppKernel`` class:: + + // app/AppKernel.php + public function registerBundles() + { + $bundles = array( + // ... + // register your bundle + new Acme\TestBundle\AcmeTestBundle(), + ); + // ... + + return $bundles; + } + +And while it doesn't do anything yet, AcmeTestBundle is now ready to be used. + +And as easy as this is, Symfony also provides a command-line interface for +generating a basic bundle skeleton: + +.. code-block:: bash + + $ php app/console generate:bundle --namespace=Acme/TestBundle + +The bundle skeleton generates a basic controller, template and routing +resource that can be customized. You'll learn more about Symfony's command-line +tools later. + +.. tip:: + + Whenever creating a new bundle or using a third-party bundle, always make + sure the bundle has been enabled in ``registerBundles()``. When using + the ``generate:bundle`` command, this is done for you. + +Bundle Directory Structure +-------------------------- + +The directory structure of a bundle is simple and flexible. By default, the +bundle system follows a set of conventions that help to keep code consistent +between all Symfony bundles. Take a look at AcmeDemoBundle, as it contains some +of the most common elements of a bundle: + +``Controller/`` + Contains the controllers of the bundle (e.g. ``RandomController.php``). + +``DependencyInjection/`` + Holds certain Dependency Injection Extension classes, which may import service + configuration, register compiler passes or more (this directory is not + necessary). + +``Resources/config/`` + Houses configuration, including routing configuration (e.g. ``routing.yml``). + +``Resources/views/`` + Holds templates organized by controller name (e.g. ``Hello/index.html.twig``). + +``Resources/public/`` + Contains web assets (images, stylesheets, etc) and is copied or symbolically + linked into the project ``web/`` directory via the ``assets:install`` console + command. + +``Tests/`` + Holds all tests for the bundle. + +A bundle can be as small or large as the feature it implements. It contains +only the files you need and nothing else. + +As you move through the book, you'll learn how to persist objects to a database, +create and validate forms, create translations for your application, write +tests and much more. Each of these has their own place and role within the +bundle. + +_`third-party bundles`: http://knpbundles.com diff --git a/book/configuration.rst b/book/configuration.rst new file mode 100644 index 00000000000..da32a0e1afe --- /dev/null +++ b/book/configuration.rst @@ -0,0 +1,281 @@ +.. index:: + single: Configuration + +Configuring Symfony (and Environments) +====================================== + +An application consists of a collection of bundles representing all the +features and capabilities of your application. Each bundle can be customized +via configuration files written in YAML, XML or PHP. By default, the main +configuration file lives in the ``app/config/`` directory and is called +either ``config.yml``, ``config.xml`` or ``config.php`` depending on which +format you prefer: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + imports: + - { resource: parameters.yml } + - { resource: security.yml } + + framework: + secret: "%secret%" + router: { resource: "%kernel.root_dir%/config/routing.yml" } + # ... + + # Twig Configuration + twig: + debug: "%kernel.debug%" + strict_variables: "%kernel.debug%" + + # ... + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + $this->import('parameters.yml'); + $this->import('security.yml'); + + $container->loadFromExtension('framework', array( + 'secret' => '%secret%', + 'router' => array( + 'resource' => '%kernel.root_dir%/config/routing.php', + ), + // ... + )); + + // Twig Configuration + $container->loadFromExtension('twig', array( + 'debug' => '%kernel.debug%', + 'strict_variables' => '%kernel.debug%', + )); + + // ... + +.. note:: + + You'll learn exactly how to load each file/format in the next section + `Environments`_. + +Each top-level entry like ``framework`` or ``twig`` defines the configuration +for a particular bundle. For example, the ``framework`` key defines the configuration +for the core Symfony FrameworkBundle and includes configuration for the +routing, templating, and other core systems. + +For now, don't worry about the specific configuration options in each section. +The configuration file ships with sensible defaults. As you read more and +explore each part of Symfony, you'll learn about the specific configuration +options of each feature. + +.. sidebar:: Configuration Formats + + Throughout the chapters, all configuration examples will be shown in all + three formats (YAML, XML and PHP). Each has its own advantages and + disadvantages. The choice of which to use is up to you: + + * *YAML*: Simple, clean and readable (learn more about YAML in + ":doc:`/components/yaml/yaml_format`"); + + * *XML*: More powerful than YAML at times and supports IDE autocompletion; + + * *PHP*: Very powerful but less readable than standard configuration formats. + +Default Configuration Dump +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can dump the default configuration for a bundle in YAML to the console using +the ``config:dump-reference`` command. Here is an example of dumping the default +FrameworkBundle configuration: + +.. code-block:: bash + + $ app/console config:dump-reference FrameworkBundle + +The extension alias (configuration key) can also be used: + +.. code-block:: bash + + $ app/console config:dump-reference framework + +.. note:: + + See the cookbook article: :doc:`/cookbook/bundles/extension` for + information on adding configuration for your own bundle. + +.. index:: + single: Environments; Introduction + +.. _environments-summary: +.. _page-creation-environments: +.. _book-page-creation-prod-cache-clear: + +Environments +------------ + +An application can run in various environments. The different environments +share the same PHP code (apart from the front controller), but use different +configuration. For instance, a ``dev`` environment will log warnings and +errors, while a ``prod`` environment will only log errors. Some files are +rebuilt on each request in the ``dev`` environment (for the developer's convenience), +but cached in the ``prod`` environment. All environments live together on +the same machine and execute the same application. + +A Symfony project generally begins with three environments (``dev``, ``test`` +and ``prod``), though creating new environments is easy. You can view your +application in different environments simply by changing the front controller +in your browser. To see the application in the ``dev`` environment, access +the application via the development front controller: + +.. code-block:: text + + http://localhost/app_dev.php/random/10 + +If you'd like to see how your application will behave in the production environment, +call the ``prod`` front controller instead: + +.. code-block:: text + + http://localhost/app.php/random/10 + +Since the ``prod`` environment is optimized for speed; the configuration, +routing and Twig templates are compiled into flat PHP classes and cached. +When viewing changes in the ``prod`` environment, you'll need to clear these +cached files and allow them to rebuild: + +.. code-block:: bash + + $ php app/console cache:clear --env=prod --no-debug + +.. note:: + + If you open the ``web/app.php`` file, you'll find that it's configured explicitly + to use the ``prod`` environment:: + + $kernel = new AppKernel('prod', false); + + You can create a new front controller for a new environment by copying + this file and changing ``prod`` to some other value. + +.. note:: + + The ``test`` environment is used when running automated tests and cannot + be accessed directly through the browser. See the :doc:`testing chapter ` + for more details. + +.. index:: + single: Environments; Configuration + +Environment Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``AppKernel`` class is responsible for actually loading the configuration +file of your choice:: + + // app/AppKernel.php + public function registerContainerConfiguration(LoaderInterface $loader) + { + $loader->load( + __DIR__.'/config/config_'.$this->getEnvironment().'.yml' + ); + } + +You already know that the ``.yml`` extension can be changed to ``.xml`` or +``.php`` if you prefer to use either XML or PHP to write your configuration. +Notice also that each environment loads its own configuration file. Consider +the configuration file for the ``dev`` environment. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config_dev.yml + imports: + - { resource: config.yml } + + framework: + router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } + profiler: { only_exceptions: false } + + # ... + + .. code-block:: xml + + + + + + + + + + + + + + + + + + .. code-block:: php + + // app/config/config_dev.php + $loader->import('config.php'); + + $container->loadFromExtension('framework', array( + 'router' => array( + 'resource' => '%kernel.root_dir%/config/routing_dev.php', + ), + 'profiler' => array('only-exceptions' => false), + )); + + // ... + +The ``imports`` key is similar to a PHP ``include`` statement and guarantees +that the main configuration file (``config.yml``) is loaded first. The rest +of the file tweaks the default configuration for increased logging and other +settings conducive to a development environment. + +Both the ``prod`` and ``test`` environments follow the same model: each environment +imports the base configuration file and then modifies its configuration values +to fit the needs of the specific environment. This is just a convention, +but one that allows you to reuse most of your configuration and customize +just pieces of it between environments. diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 453475f07c3..413a5637415 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -681,7 +681,7 @@ at how migrating the blog from flat PHP to Symfony has improved life: 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 :ref:`autoloading `, + 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 diff --git a/book/index.rst b/book/index.rst index 70d6cd2558e..e60cc4879b4 100644 --- a/book/index.rst +++ b/book/index.rst @@ -11,6 +11,8 @@ The Book controller routing templating + configuration + bundles doctrine propel testing diff --git a/book/installation.rst b/book/installation.rst index f0a1cd5cd92..a2bdb8f70bd 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -110,7 +110,7 @@ pass ``lts`` as the second argument of the ``new`` command: $ symfony new my_project_name lts # Windows - c:\projects\> php symfony.phar new my_project_name lts + c:\projects\> php symfony new my_project_name lts Read the :doc:`Symfony Release process ` to better understand why there are several Symfony versions and which one @@ -315,6 +315,30 @@ several minutes to complete. A good security practice is to execute this command regularly to be able to update or replace compromised dependencies as soon as possible. +Installing the Symfony Demo Application +--------------------------------------- + +The Symfony Demo application is a fully-functional application that shows the +recommended way to develop Symfony applications. The application has been +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: + +.. code-block:: bash + + # Linux, Mac OS X + $ symfony demo + + # Windows + c:\projects\> php symfony demo + +Once downloaded, enter into the ``symfony_demo/`` directory and run the PHP's +built-in web server executing the ``php app/console server:run`` command. Access +to the ``http://localhost:8000`` URL in your browser to start using the Symfony +Demo application. + .. _installing-a-symfony2-distribution: Installing a Symfony Distribution diff --git a/book/map.rst.inc b/book/map.rst.inc index d432bfe3674..ab7cada4433 100644 --- a/book/map.rst.inc +++ b/book/map.rst.inc @@ -5,6 +5,8 @@ * :doc:`/book/controller` * :doc:`/book/routing` * :doc:`/book/templating` +* :doc:`/book/configuration` +* :doc:`/book/bundles` * :doc:`/book/doctrine` * :doc:`/book/propel` * :doc:`/book/testing` diff --git a/book/page_creation.rst b/book/page_creation.rst index 48217d53ece..37e62d94253 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -2,207 +2,193 @@ single: Page creation .. _creating-pages-in-symfony2: +.. _creating-pages-in-symfony: -Creating Pages in Symfony -========================= +Create your First Page in Symfony +================================= -Creating a new page in Symfony is a simple two-step process: +Creating a new page - whether it's an HTML page or a JSON endpoint - is a +simple two-step process: -* *Create a route*: A route defines the URL (e.g. ``/about``) to your page - and specifies a controller (which is a PHP function) that Symfony should - execute when the URL of an incoming request matches the route path; +#. *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 a PHP function that takes the incoming - request and transforms it into the Symfony ``Response`` object that's - returned to the user. +#. *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. -This simple approach is beautiful because it matches the way that the Web works. -Every interaction on the Web is initiated by an HTTP request. The job of -your application is simply to interpret the request and return the appropriate -HTTP response. - -Symfony follows this philosophy and provides you with tools and conventions -to keep your application organized as it grows in users and complexity. +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; Environments & Front Controllers + single: Page creation; Example -.. _page-creation-environments: +Creating a Page: Route and Controller +------------------------------------- -Environments & Front Controllers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. tip:: -Every Symfony application runs within an :term:`environment`. An environment -is a specific set of configuration and loaded bundles, represented by a string. -The same application can be run with different configurations by running the -application in different environments. Symfony comes with three environments -defined — ``dev``, ``test`` and ``prod`` — but you can create your own as well. - -Environments are useful by allowing a single application to have a dev environment -built for debugging and a production environment optimized for speed. You might -also load specific bundles based on the selected environment. For example, -Symfony comes with the WebProfilerBundle (described below), enabled only -in the ``dev`` and ``test`` environments. - -Symfony comes with two web-accessible front controllers: ``app_dev.php`` -provides the ``dev`` environment, and ``app.php`` provides the ``prod`` environment. -All web accesses to Symfony normally go through one of these front controllers. -(The ``test`` environment is normally only used when running unit tests, and so -doesn't have a dedicated front controller. The console tool also provides a -front controller that can be used with any environment.) - -When the front controller initializes the kernel, it provides two parameters: -the environment, and also whether the kernel should run in debug mode. -To make your application respond faster, Symfony maintains a cache under the -``app/cache/`` directory. When debug mode is enabled (such as ``app_dev.php`` -does by default), this cache is flushed automatically whenever you make changes -to any code or configuration. When running in debug mode, Symfony runs -slower, but your changes are reflected without having to manually clear the -cache. + Before continuing, make sure you've read the :doc:`Installation ` + chapter and can access your new Symfony app in the browser. -.. index:: - single: Page creation; Example +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``:: + + // src/AppBundle/Controller/LuckyController.php + namespace AppBundle\Controller; -The "Random Number" Page ------------------------- + use Symfony\Bundle\FrameworkBundle\Controller\Controller; + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + use Symfony\Component\HttpFoundation\Response; -In this chapter, you'll develop an application that can generate random numbers. -When you're finished, the user will be able to get a random number between ``1`` -and the upper limit set by the URL: + class LuckyController + { + /** + * @Route("/lucky/number") + */ + public function numberAction() + { + $number = rand(0, 100); -.. code-block:: text + return new Response( + 'Lucky number: '.$number.'' + ); + } + } - http://localhost/app_dev.php/random/100 +Before diving into this, test it out! -Actually, you'll be able to replace ``100`` with any other number to generate -numbers up to that upper limit. To create the page, follow the simple two-step -process. + http://localhost:8000/app_dev.php/lucky/number -.. note:: +.. tip:: - The tutorial assumes that you've already downloaded Symfony and configured - your webserver. The above URL assumes that ``localhost`` points to the - ``web`` directory of your new Symfony project. For detailed information - on this process, see the documentation on the web server you are using. - Here are some relevant documentation pages for the web server you might be using: + If you setup 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``. - * For Apache HTTP Server, refer to `Apache's DirectoryIndex documentation`_ - * For Nginx, refer to `Nginx HttpCoreModule location documentation`_ +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. -Before you begin: Create the Bundle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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. -Before you begin, you'll need to create a *bundle*. In Symfony, a :term:`bundle` -is like a plugin, except that all the code in your application will live -inside a bundle. +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). -A bundle is nothing more than a directory that houses everything related -to a specific feature, including PHP classes, configuration, and even stylesheets -and JavaScript files (see :ref:`page-creation-bundles`). +.. sidebar:: What's the ``app_dev.php`` in the URL? -Depending on the way you installed Symfony, you may already have a bundle called -AcmeDemoBundle. Browse the ``src/`` directory of your project and check -if there is a ``DemoBundle/`` directory inside an ``Acme/`` directory. If those -directories already exist, skip the rest of this section and go directly to -create the route. + Great question! By including ``app_dev.php`` in the URL, you're executing + Symfony through a file - ``web/app_dev.php`` - that boots it in the ``dev`` + environment. This enables great debugging tools and rebuilds cached + files automatically. For production, you'll use clean URLs - like + ``http://localhost:8000/lucky/number`` - that execute a different file - + ``app.php`` - that's optimized for speed. To learn more about this and + environments, see :ref:`book-page-creation-prod-cache-clear`. -To create a bundle called AcmeDemoBundle (a play bundle that you'll -build in this chapter), run the following command and follow the on-screen -instructions (use all the default options): +Creating a JSON Response +~~~~~~~~~~~~~~~~~~~~~~~~ -.. code-block:: bash +The ``Response`` object you return in your controller can contain HTML, JSON +or even a binary file like an image or PDF. You can easily set HTTP headers +or the status code. - $ php app/console generate:bundle --namespace=Acme/DemoBundle --format=yml +Suppose you want to create a JSON endpoint that returns the lucky number. +Just add a second method to ``LuckyController``:: -Behind the scenes, a directory is created for the bundle at ``src/Acme/DemoBundle``. -A line is also automatically added to the ``app/AppKernel.php`` file so that -the bundle is registered with the kernel:: + // src/AppBundle/Controller/LuckyController.php + // ... - // app/AppKernel.php - public function registerBundles() + class LuckyController { - $bundles = array( - // ... - new Acme\DemoBundle\AcmeDemoBundle(), - ); // ... - return $bundles; - } - -Now that you have a bundle setup, you can begin building your application -inside the bundle. - -Step 1: Create the Route -~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, the routing configuration file in a Symfony application is -located at ``app/config/routing.yml``. Like all configuration in Symfony, -you can also choose to use XML or PHP out of the box to configure routes. - -If you look at the main routing file, you'll see that Symfony already added an -entry when you generated the AcmeDemoBundle: + /** + * @Route("/api/lucky/number") + */ + public function apiNumberAction() + { + $data = array( + 'lucky_number' => rand(0, 100), + ); -.. configuration-block:: + return new Response( + json_encode($data), + 200, + array('Content-Type' => 'application/json') + ); + } + } - .. code-block:: yaml +Try this out in your browser: - # app/config/routing.yml - acme_website: - resource: "@AcmeDemoBundle/Resources/config/routing.yml" - prefix: / + http://localhost:8000/app_dev.php/api/lucky/number - .. code-block:: xml +You can even shorten this with the handy :class:`Symfony\\Component\\HttpFoundation\\JsonResponse`:: - - - + // src/AppBundle/Controller/LuckyController.php + // ... - - + // --> don't forget this new use statement + use Symfony\Component\HttpFoundation\JsonResponse; - .. code-block:: php + class LuckyController + { + // ... - // app/config/routing.php - use Symfony\Component\Routing\RouteCollection; + /** + * @Route("/api/lucky/number") + */ + public function apiNumberAction() + { + $data = array( + 'lucky_number' => rand(0, 100), + ); - $acmeDemo = $loader->import('@AcmeDemoBundle/Resources/config/routing.php'); - $acmeDemo->addPrefix('/'); + // calls json_encode and sets the Content-Type header + return new JsonResponse($data); + } + } - $collection = new RouteCollection(); - $collection->addCollection($acmeDemo); +Dynamic URL Patterns: /lucky/number/{count} +------------------------------------------- - return $collection; +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: -This entry is pretty basic: it tells Symfony to load routing configuration -from the ``Resources/config/routing.yml`` (``routing.xml`` or ``routing.php`` -in the XML and PHP code example respectively) file that lives inside the -AcmeDemoBundle. This means that you place routing configuration directly in -``app/config/routing.yml`` or organize your routes throughout your application, -and import them from here. +.. configuration-block:: -.. note:: + .. code-block:: php-annotations - You are not limited to load routing configurations that are of the same - format. For example, you could also load a YAML file in an XML configuration - and vice versa. + // src/AppBundle/Controller/LuckyController.php + // ... -Now that the ``routing.yml`` file from the bundle is being imported, add -the new route that defines the URL of the page that you're about to create: + class LuckyController + { + /** + * @Route("/lucky/number/{count}") + */ + public function numberAction() + { + // ... + } -.. configuration-block:: + // ... + } .. code-block:: yaml - # src/Acme/DemoBundle/Resources/config/routing.yml - random: - path: /random/{limit} - defaults: { _controller: AcmeDemoBundle:Random:index } + # app/config/routing.yml + lucky_number: + path: /lucky/number/{count} + defaults: { _controller: AppBundle:Lucky:number } .. code-block:: xml @@ -213,8 +199,8 @@ the new route that defines the URL of the page that you're about to create: xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - - AcmeDemoBundle:Random:index + + AppBundle:Lucky:number @@ -225,595 +211,278 @@ the new route that defines the URL of the page that you're about to create: use Symfony\Component\Routing\Route; $collection = new RouteCollection(); - $collection->add('random', new Route('/random/{limit}', array( - '_controller' => 'AcmeDemoBundle:Random:index', + $collection->add('lucky_number', new Route('/lucky/number/{count}', array( + '_controller' => 'AppBundle:Lucky:number', ))); return $collection; -The routing consists of two basic pieces: the ``path``, which is the URL -that this route will match, and a ``defaults`` array, which specifies the -controller that should be executed. The placeholder syntax in the path -(``{limit}``) is a wildcard. It means that ``/random/10``, ``/random/327`` -or any other similar URL will match this route. The ``{limit}`` placeholder -parameter will also be passed to the controller so that you can use its value -to generate the proper random number. - -.. note:: - - The routing system has many more great features for creating flexible - and powerful URL structures in your application. For more details, see - the chapter all about :doc:`Routing `. - -Step 2: Create the Controller -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When a URL such as ``/random/10`` is handled by the application, the ``random`` -route is matched and the ``AcmeDemoBundle:Random:index`` controller is executed -by the framework. The second step of the page-creation process is to create -that controller. - -The controller - ``AcmeDemoBundle:Random:index`` is the *logical* name of -the controller, and it maps to the ``indexAction`` method of a PHP class -called ``Acme\DemoBundle\Controller\RandomController``. Start by creating this -file inside your AcmeDemoBundle:: +Because of the ``{count}`` "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:: - // src/Acme/DemoBundle/Controller/RandomController.php - namespace Acme\DemoBundle\Controller; + // src/AppBundle/Controller/LuckyController.php + // ... - class RandomController + class LuckyController { - } - -In reality, the controller is nothing more than a PHP method that you create -and Symfony executes. This is where your code uses information from the request -to build and prepare the resource being requested. Except in some advanced -cases, the end product of a controller is always the same: a Symfony ``Response`` -object. - -Create the ``indexAction`` method that Symfony will execute when the ``random`` -route is matched:: - // src/Acme/DemoBundle/Controller/RandomController.php - namespace Acme\DemoBundle\Controller; - - use Symfony\Component\HttpFoundation\Response; - - class RandomController - { - public function indexAction($limit) + /** + * @Route("/lucky/number/{count}") + */ + public function numberAction($count) { + $numbers = array(); + for ($i = 0; $i < $count; $i++) { + $numbers[] = rand(0, 100); + } + $numbersList = implode(', ', $numbers); + return new Response( - 'Number: '.rand(1, $limit).'' + 'Lucky numbers: '.$numbersList.'' ); } - } -The controller is simple: it creates a new ``Response`` object, whose first -argument is the content that should be used in the response (a small HTML -page in this example). - -Congratulations! After creating only a route and a controller, you already -have a fully-functional page! If you've setup everything correctly, your -application should generate a random number for you: - -.. code-block:: text - - http://localhost/app_dev.php/random/10 - -.. _book-page-creation-prod-cache-clear: - -.. tip:: + // ... + } - You can also view your app in the "prod" :ref:`environment ` - by visiting: +Try it by going to ``/lucky/number/XX`` - replacing XX with *any* number: - .. code-block:: text + http://localhost:8000/app_dev.php/lucky/number/7 - http://localhost/app.php/random/10 +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. - If you get an error, it's likely because you need to clear your cache - by running: +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). - .. code-block:: bash +Find out about all of this and become a routing expert in the +:doc:`Routing ` chapter. - $ php app/console cache:clear --env=prod --no-debug +Rendering a Template (with the Service Container) +------------------------------------------------- -An optional, but common, third step in the process is to create a template. +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 +easy, powerful and actually quite fun. -.. note:: +So far, ``LuckyController`` doesn't extend any base class. The easiest way +to use Twig - or many other tools in Symfony - is to extend Symfony's base +:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class:: + + // src/AppBundle/Controller/LuckyController.php + // ... - Controllers are the main entry point for your code and a key ingredient - when creating pages. Much more information can be found in the - :doc:`Controller Chapter `. + // --> add this new use statement + use Symfony\Bundle\FrameworkBundle\Controller\Controller; -Optional Step 3: Create the Template -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class LuckyController extends Controller + { + // ... + } -Templates allow you to move all the presentation code (e.g. HTML) into -a separate file and reuse different portions of the page layout. Instead -of writing the HTML inside the controller, render a template instead: +Using the ``templating`` Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code-block:: php - :linenos: +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 +called *services*, and Symfony ships with a service object that can render +Twig templates, another that can log messages and many more. - // src/Acme/DemoBundle/Controller/RandomController.php - namespace Acme\DemoBundle\Controller; +To render a Twig template, use a service called ``templating``:: - use Symfony\Bundle\FrameworkBundle\Controller\Controller; + // src/AppBundle/Controller/LuckyController.php + // ... - class RandomController extends Controller + class LuckyController extends Controller { - public function indexAction($limit) + /** + * @Route("/lucky/number/{count}") + */ + public function numberAction($count) { - $number = rand(1, $limit); + // ... + $numbersList = implode(', ', $numbers); - return $this->render( - 'AcmeDemoBundle:Random:index.html.twig', - array('number' => $number) + $html = $this->container->get('templating')->render( + 'lucky/number.html.twig', + array('luckyNumberList' => $numbersList) ); - // render a PHP template instead - // return $this->render( - // 'AcmeDemoBundle:Random:index.html.php', - // array('number' => $number) - // ); + return new Response($html); } - } - -.. note:: - - In order to use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render` - method, your controller must extend the - :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class, - which adds shortcuts for tasks that are common inside controllers. This - is done in the above example by adding the ``use`` statement on line 4 - and then extending ``Controller`` on line 6. - -The ``render()`` method creates a ``Response`` object filled with the content -of the given, rendered template. Like any other controller, you will ultimately -return that ``Response`` object. - -Notice that there are two different examples for rendering the template. -By default, Symfony supports two different templating languages: classic -PHP templates and the succinct but powerful `Twig`_ templates. Don't be -alarmed - you're free to choose either or even both in the same project. - -The controller renders the ``AcmeDemoBundle:Random:index.html.twig`` template, -which uses the following naming convention: - - **BundleName**:**ControllerName**:**TemplateName** - -This is the *logical* name of the template, which is mapped to a physical -location using the following convention. - - **/path/to/BundleName**/Resources/views/**ControllerName**/**TemplateName** - -In this case, AcmeDemoBundle is the bundle name, ``Random`` is the -controller, and ``index.html.twig`` the template: - -.. configuration-block:: - - .. code-block:: jinja - :linenos: - - {# src/Acme/DemoBundle/Resources/views/Random/index.html.twig #} - {% extends '::base.html.twig' %} - - {% block body %} - Number: {{ number }} - {% endblock %} - - .. code-block:: html+php - - - extend('::base.html.php') ?> - Number: escape($number) ?> - -Step through the Twig template line-by-line: - -* *line 2*: The ``extends`` token defines a parent template. The template - explicitly defines a layout file inside of which it will be placed. - -* *line 4*: The ``block`` token says that everything inside should be placed - inside a block called ``body``. As you'll see, it's the responsibility - of the parent template (``base.html.twig``) to ultimately render the - block called ``body``. - -The parent template, ``::base.html.twig``, is missing both the **BundleName** -and **ControllerName** portions of its name (hence the double colon (``::``) -at the beginning). This means that the template lives outside of the bundle -and in the ``app`` directory: - -.. configuration-block:: - - .. code-block:: html+jinja - - {# app/Resources/views/base.html.twig #} - - - - - {% block title %}Welcome!{% endblock %} - {% block stylesheets %}{% endblock %} - - - - {% block body %}{% endblock %} - {% block javascripts %}{% endblock %} - - - - .. code-block:: html+php - - - - - - - <?php $view['slots']->output('title', 'Welcome!') ?> - output('stylesheets') ?> - - - - output('_content') ?> - output('javascripts') ?> - - - -The base template file defines the HTML layout and renders the ``body`` block -that you defined in the ``index.html.twig`` template. It also renders a ``title`` -block, which you could choose to define in the ``index.html.twig`` template. -Since you did not define the ``title`` block in the child template, it defaults -to "Welcome!". - -Templates are a powerful way to render and organize the content for your -page. A template can render anything, from HTML markup, to CSS code, or anything -else that the controller may need to return. - -In the lifecycle of handling a request, the templating engine is simply -an optional tool. Recall that the goal of each controller is to return a -``Response`` object. Templates are a powerful, but optional, tool for creating -the content for that ``Response`` object. - -.. index:: - single: Directory Structure - -The Directory Structure ------------------------ - -After just a few short sections, you already understand the philosophy behind -creating and rendering pages in Symfony. You've also already begun to see -how Symfony projects are structured and organized. By the end of this section, -you'll know where to find and put different types of files and why. - -Though entirely flexible, by default, each Symfony :term:`application` has -the same basic and recommended directory structure: - -``app/`` - This directory contains the application configuration. - -``src/`` - All the project PHP code is stored under this directory. - -``vendor/`` - Any vendor libraries are placed here by convention. - -``web/`` - This is the web root directory and contains any publicly accessible files. - -.. seealso:: - - You can easily override the default directory structure. See - :doc:`/cookbook/configuration/override_dir_structure` for more - information. - -.. _the-web-directory: - -The Web Directory -~~~~~~~~~~~~~~~~~ - -The web root directory is the home of all public and static files including -images, stylesheets, and JavaScript files. It is also where each -:term:`front controller` lives:: - - // web/app.php - require_once __DIR__.'/../app/bootstrap.php.cache'; - require_once __DIR__.'/../app/AppKernel.php'; - - use Symfony\Component\HttpFoundation\Request; - - $kernel = new AppKernel('prod', false); - $kernel->loadClassCache(); - $kernel->handle(Request::createFromGlobals())->send(); - -The front controller file (``app.php`` in this example) is the actual PHP -file that's executed when using a Symfony application and its job is to -use a Kernel class, ``AppKernel``, to bootstrap the application. - -.. tip:: - - Having a front controller means different and more flexible URLs than - are used in a typical flat PHP application. When using a front controller, - URLs are formatted in the following way: - - .. code-block:: text - - http://localhost/app.php/random/10 - - The front controller, ``app.php``, is executed and the "internal:" URL - ``/random/10`` is routed internally using the routing configuration. - By using Apache ``mod_rewrite`` rules, you can force the ``app.php`` file - to be executed without needing to specify it in the URL: - - .. code-block:: text - - http://localhost/random/10 - -Though front controllers are essential in handling every request, you'll -rarely need to modify or even think about them. They'll be mentioned again -briefly in the `Environments`_ section. - -The Application (``app``) Directory -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As you saw in the front controller, the ``AppKernel`` class is the main entry -point of the application and is responsible for all configuration. As such, -it is stored in the ``app/`` directory. - -This class must implement two methods that define everything that Symfony -needs to know about your application. You don't even need to worry about -these methods when starting - Symfony fills them in for you with sensible -defaults. - -``registerBundles()`` - Returns an array of all bundles needed to run the application (see - :ref:`page-creation-bundles`). - -``registerContainerConfiguration()`` - Loads the main application configuration resource file (see the - `Application Configuration`_ section). - -In day-to-day development, you'll mostly use the ``app/`` directory to modify -configuration and routing files in the ``app/config/`` directory (see -`Application Configuration`_). It also contains the application cache -directory (``app/cache``), a log directory (``app/logs``) and a directory -for application-level resource files, such as templates (``app/Resources``). -You'll learn more about each of these directories in later chapters. - -.. _autoloading-introduction-sidebar: - -.. sidebar:: Autoloading - - When Symfony is loading, a special file - ``vendor/autoload.php`` - is - included. This file is created by Composer and will autoload all - application files living in the ``src/`` folder as well as all - third-party libraries mentioned in the ``composer.json`` file. - - Because of the autoloader, you never need to worry about using ``include`` - or ``require`` statements. Instead, Composer uses the namespace of a class - to determine its location and automatically includes the file on your - behalf the instant you need a class. - - The autoloader is already configured to look in the ``src/`` directory - for any of your PHP classes. For autoloading to work, the class name and - path to the file have to follow the same pattern: - - .. code-block:: text - - Class Name: - Acme\DemoBundle\Controller\RandomController - Path: - src/Acme/DemoBundle/Controller/RandomController.php - -The Source (``src``) Directory -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Put simply, the ``src/`` directory contains all the actual code (PHP code, -templates, configuration files, stylesheets, etc) that drives *your* application. -When developing, the vast majority of your work will be done inside one or -more bundles that you create in this directory. - -But what exactly is a :term:`bundle`? - -.. _page-creation-bundles: - -The Bundle System ------------------ - -A bundle is similar to a plugin in other software, but even better. The key -difference is that *everything* is a bundle in Symfony, including both the -core framework functionality and the code written for your application. -Bundles are first-class citizens in Symfony. This gives you the flexibility -to use pre-built features packaged in `third-party bundles`_ or to distribute -your own bundles. It makes it easy to pick and choose which features to enable -in your application and to optimize them the way you want. - -.. note:: + // ... + } - While you'll learn the basics here, an entire cookbook entry is devoted - to the organization and best practices of :doc:`bundles `. +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. -A bundle is simply a structured set of files within a directory that implement -a single feature. You might create a BlogBundle, a ForumBundle or -a bundle for user management (many of these exist already as open source -bundles). Each directory contains everything related to that feature, including -PHP files, templates, stylesheets, JavaScripts, tests and anything else. -Every aspect of a feature exists in a bundle and every feature lives in a -bundle. +But this can get even easier! By extending the ``Controller`` class, you +also get a lot of shortcut methods, like ``render()``:: -An application is made up of bundles as defined in the ``registerBundles()`` -method of the ``AppKernel`` class:: + // src/AppBundle/Controller/LuckyController.php + // ... - // app/AppKernel.php - public function registerBundles() + /** + * @Route("/lucky/number/{count}") + */ + public function numberAction($count) { - $bundles = array( - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\TwigBundle\TwigBundle(), - new Symfony\Bundle\MonologBundle\MonologBundle(), - new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), - new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), - new Symfony\Bundle\AsseticBundle\AsseticBundle(), - new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), + // ... + + /* + $html = $this->container->get('templating')->render( + 'lucky/number.html.twig', + array('luckyNumberList' => $numbersList) ); - if (in_array($this->getEnvironment(), array('dev', 'test'))) { - $bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); - $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); - $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); - $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); - } + return new Response($html); + */ - return $bundles; + // render: a shortcut that does the same as above + return $this->render( + 'lucky/number.html.twig', + array('luckyNumberList' => $numbersList) + ); } -With the ``registerBundles()`` method, you have total control over which bundles -are used by your application (including the core Symfony bundles). +Learn more about these shortcut methods and how they work in the +:doc:`Controller ` chapter. .. tip:: - A bundle can live *anywhere* as long as it can be autoloaded (via the - autoloader configured at ``app/autoload.php``). - -Creating a Bundle -~~~~~~~~~~~~~~~~~ + For more advanced users, you can also + :doc:`register your controllers as services `. -The Symfony Standard Edition comes with a handy task that creates a fully-functional -bundle for you. Of course, creating a bundle by hand is pretty easy as well. +Create the Template +~~~~~~~~~~~~~~~~~~~ -To show you how simple the bundle system is, create a new bundle called -AcmeTestBundle and enable it. - -.. tip:: +If you refresh now, you'll get an error: - The ``Acme`` portion is just a dummy name that should be replaced by - some "vendor" name that represents you or your organization (e.g. - ABCTestBundle for some company named ``ABC``). + Unable to find template "lucky/number.html.twig" -Start by creating a ``src/Acme/TestBundle/`` directory and adding a new file -called ``AcmeTestBundle.php``:: +Fix that by creating a new ``app/Resources/views/lucky`` directory and putting +a ``number.html.twig`` file inside of it: - // src/Acme/TestBundle/AcmeTestBundle.php - namespace Acme\TestBundle; +.. configuration-block:: - use Symfony\Component\HttpKernel\Bundle\Bundle; + .. code-block:: jinja - class AcmeTestBundle extends Bundle - { - } + {# app/Resources/views/lucky/number.html.twig #} + {% extends 'base.html.twig' %} -.. tip:: + {% block body %} +

Lucky Numbers: {{ luckyNumberList }}

+ {% endblock %} - The name AcmeTestBundle follows the standard - :ref:`Bundle naming conventions `. You could - also choose to shorten the name of the bundle to simply TestBundle by naming - this class TestBundle (and naming the file ``TestBundle.php``). + .. code-block:: html+php -This empty class is the only piece you need to create the new bundle. Though -commonly empty, this class is powerful and can be used to customize the behavior -of the bundle. + + extend('base.html.php') ?> -Now that you've created the bundle, enable it via the ``AppKernel`` class:: + start('body') ?> +

Lucky Numbers: escape($luckyNumberList) ?> + stop() ?> - // app/AppKernel.php - public function registerBundles() - { - $bundles = array( - // ... - // register your bundle - new Acme\TestBundle\AcmeTestBundle(), - ); - // ... +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. - return $bundles; - } +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. -And while it doesn't do anything yet, AcmeTestBundle is now ready to be used. +Refresh to see your template in action! -And as easy as this is, Symfony also provides a command-line interface for -generating a basic bundle skeleton: + http://localhost:8000/app_dev.php/lucky/number/9 -.. code-block:: bash +If you view the source code, you now have a basic HTML structure thanks to +``base.html.twig``. - $ php app/console generate:bundle --namespace=Acme/TestBundle +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 +the :doc:`Templating ` chapter. -The bundle skeleton generates with a basic controller, template and routing -resource that can be customized. You'll learn more about Symfony's command-line -tools later. +Exploring the Project +--------------------- -.. tip:: +You've already created a flexible URL, rendered a template that uses inheritance +and created a JSON endpoint. Nice! - Whenever creating a new bundle or using a third-party bundle, always make - sure the bundle has been enabled in ``registerBundles()``. When using - the ``generate:bundle`` command, this is done for you. +It's time to explore and demystify the files in your project. You've already +worked inside the two most important directories: -Bundle Directory Structure -~~~~~~~~~~~~~~~~~~~~~~~~~~ +``app/`` + Contains things like configuration and templates. Basically, anything + that is *not* PHP code goes here. -The directory structure of a bundle is simple and flexible. By default, the -bundle system follows a set of conventions that help to keep code consistent -between all Symfony bundles. Take a look at AcmeDemoBundle, as it contains some -of the most common elements of a bundle: +``src/`` + Your PHP code lives here. -``Controller/`` - Contains the controllers of the bundle (e.g. ``RandomController.php``). +99% of the time, you'll be working in ``src/`` (PHP files) or ``app/`` (everything +else). As you get more advanced, you'll learn what can be done inside each +of these. -``DependencyInjection/`` - Holds certain Dependency Injection Extension classes, which may import service - configuration, register compiler passes or more (this directory is not - necessary). +The ``app/`` directory also holds a few other things, like the cache directory +``app/cache/``, the logs directory ``app/logs/`` and ``app/AppKernel.php``, +which you'll use to enable new bundles (and one of a *very* short list of +PHP files in ``app/``). -``Resources/config/`` - Houses configuration, including routing configuration (e.g. ``routing.yml``). +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. -``Resources/views/`` - Holds templates organized by controller name (e.g. ``Hello/index.html.twig``). +So what about the other directories in the project? -``Resources/public/`` - Contains web assets (images, stylesheets, etc) and is copied or symbolically - linked into the project ``web/`` directory via the ``assets:install`` console - command. +``vendor/`` + Vendor (i.e. third-party) libraries and bundles are downloaded here by + the `Composer`_ package manager. -``Tests/`` - Holds all tests for the bundle. +``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``). -A bundle can be as small or large as the feature it implements. It contains -only the files you need and nothing else. +.. seealso:: -As you move through the book, you'll learn how to persist objects to a database, -create and validate forms, create translations for your application, write -tests and much more. Each of these has their own place and role within the -bundle. + Symfony is flexible. If you need to, you can easily override the default + directory structure. See :doc:`/cookbook/configuration/override_dir_structure`. Application Configuration ------------------------- -An application consists of a collection of bundles representing all the -features and capabilities of your application. Each bundle can be customized -via configuration files written in YAML, XML or PHP. By default, the main -configuration file lives in the ``app/config/`` directory and is called -either ``config.yml``, ``config.xml`` or ``config.php`` depending on which -format you prefer: +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``: .. configuration-block:: .. code-block:: yaml # app/config/config.yml - imports: - - { resource: parameters.yml } - - { resource: security.yml } + # ... framework: - secret: "%secret%" - router: { resource: "%kernel.root_dir%/config/routing.yml" } + secret: "%secret%" + router: + resource: "%kernel.root_dir%/config/routing.yml" # ... - # Twig Configuration twig: debug: "%kernel.debug%" strict_variables: "%kernel.debug%" @@ -835,10 +504,7 @@ format you prefer: http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd"> - - - - + @@ -854,8 +520,7 @@ format you prefer: .. code-block:: php // app/config/config.php - $this->import('parameters.yml'); - $this->import('security.yml'); + // ... $container->loadFromExtension('framework', array( 'secret' => '%secret%', @@ -873,234 +538,43 @@ format you prefer: // ... -.. note:: - - You'll learn exactly how to load each file/format in the next section - `Environments`_. - -Each top-level entry like ``framework`` or ``twig`` defines the configuration -for a particular bundle. For example, the ``framework`` key defines the configuration -for the core Symfony FrameworkBundle and includes configuration for the -routing, templating, and other core systems. - -For now, don't worry about the specific configuration options in each section. -The configuration file ships with sensible defaults. As you read more and -explore each part of Symfony, you'll learn about the specific configuration -options of each feature. - -.. sidebar:: Configuration Formats - - Throughout the chapters, all configuration examples will be shown in all - three formats (YAML, XML and PHP). Each has its own advantages and - disadvantages. The choice of which to use is up to you: - - * *YAML*: Simple, clean and readable (learn more about YAML in - ":doc:`/components/yaml/yaml_format`"); - - * *XML*: More powerful than YAML at times and supports IDE autocompletion; - - * *PHP*: Very powerful but less readable than standard configuration formats. - -Default Configuration Dump -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can dump the default configuration for a bundle in YAML to the console using -the ``config:dump-reference`` command. Here is an example of dumping the default -FrameworkBundle configuration: - -.. code-block:: bash - - $ app/console config:dump-reference FrameworkBundle +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. -The extension alias (configuration key) can also be used: +Or, to get a big example dump of all of the valid configuration under a key, +use the handy ``app/console`` command: .. code-block:: bash $ app/console config:dump-reference framework -.. note:: - - See the cookbook article: :doc:`/cookbook/bundles/extension` for - information on adding configuration for your own bundle. - -.. index:: - single: Environments; Introduction - -.. _environments-summary: +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. -Environments +What's Next? ------------ -An application can run in various environments. The different environments -share the same PHP code (apart from the front controller), but use different -configuration. For instance, a ``dev`` environment will log warnings and -errors, while a ``prod`` environment will only log errors. Some files are -rebuilt on each request in the ``dev`` environment (for the developer's convenience), -but cached in the ``prod`` environment. All environments live together on -the same machine and execute the same application. - -A Symfony project generally begins with three environments (``dev``, ``test`` -and ``prod``), though creating new environments is easy. You can view your -application in different environments simply by changing the front controller -in your browser. To see the application in the ``dev`` environment, access -the application via the development front controller: - -.. code-block:: text - - http://localhost/app_dev.php/random/10 - -If you'd like to see how your application will behave in the production environment, -call the ``prod`` front controller instead: - -.. code-block:: text - - http://localhost/app.php/random/10 - -Since the ``prod`` environment is optimized for speed; the configuration, -routing and Twig templates are compiled into flat PHP classes and cached. -When viewing changes in the ``prod`` environment, you'll need to clear these -cached files and allow them to rebuild: - -.. code-block:: bash - - $ php app/console cache:clear --env=prod --no-debug - -.. note:: - - If you open the ``web/app.php`` file, you'll find that it's configured explicitly - to use the ``prod`` environment:: - - $kernel = new AppKernel('prod', false); - - You can create a new front controller for a new environment by copying - this file and changing ``prod`` to some other value. - -.. note:: - - The ``test`` environment is used when running automated tests and cannot - be accessed directly through the browser. See the :doc:`testing chapter ` - for more details. - -.. index:: - single: Environments; Configuration - -Environment Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``AppKernel`` class is responsible for actually loading the configuration -file of your choice:: - - // app/AppKernel.php - public function registerContainerConfiguration(LoaderInterface $loader) - { - $loader->load( - __DIR__.'/config/config_'.$this->getEnvironment().'.yml' - ); - } - -You already know that the ``.yml`` extension can be changed to ``.xml`` or -``.php`` if you prefer to use either XML or PHP to write your configuration. -Notice also that each environment loads its own configuration file. Consider -the configuration file for the ``dev`` environment. - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/config_dev.yml - imports: - - { resource: config.yml } - - framework: - router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } - profiler: { only_exceptions: false } - - # ... - - .. code-block:: xml - - - - - - - - - - - - - - - - - - .. code-block:: php - - // app/config/config_dev.php - $loader->import('config.php'); - - $container->loadFromExtension('framework', array( - 'router' => array( - 'resource' => '%kernel.root_dir%/config/routing_dev.php', - ), - 'profiler' => array('only-exceptions' => false), - )); - - // ... - -The ``imports`` key is similar to a PHP ``include`` statement and guarantees -that the main configuration file (``config.yml``) is loaded first. The rest -of the file tweaks the default configuration for increased logging and other -settings conducive to a development environment. - -Both the ``prod`` and ``test`` environments follow the same model: each environment -imports the base configuration file and then modifies its configuration values -to fit the needs of the specific environment. This is just a convention, -but one that allows you to reuse most of your configuration and customize -just pieces of it between environments. - -Summary -------- - -Congratulations! You've now seen every fundamental aspect of Symfony and have -hopefully discovered how easy and flexible it can be. And while there are -*a lot* of features still to come, be sure to keep the following basic points -in mind: - -* Creating a page is a three-step process involving a **route**, a **controller** - and (optionally) a **template**; - -* Each project contains just a few main directories: ``web/`` (web assets and - the front controllers), ``app/`` (configuration), ``src/`` (your bundles), - and ``vendor/`` (third-party code) (there's also a ``bin/`` directory that's - used to help updated vendor libraries); +Congrats! You're already starting to master Symfony and learn a whole new +way of building beautiful, functional, fast and maintainable apps. -* Each feature in Symfony (including the Symfony Framework core) is organized - into a *bundle*, which is a structured set of files for that feature; +Ok, time to finish mastering the fundamentals by reading these chapters: -* The **configuration** for each bundle lives in the ``Resources/config`` - directory of the bundle and can be specified in YAML, XML or PHP; +* :doc:`/book/controller` +* :doc:`/book/routing` +* :doc:`/book/templating` -* The global **application configuration** lives in the ``app/config`` - directory; +Then, learn about Symfony's :doc:`service container ` +the :doc:`form system `, using :doc:`Doctrine ` +if you need to query a database and more. in the :doc:`Symfony Book `. -* Each **environment** is accessible via a different front controller (e.g. - ``app.php`` and ``app_dev.php``) and loads a different configuration file. +There's also a :doc:`Cookbook ` *packed* with more advanced +"how to" articles to solve *a lot* of problems. -From here, each chapter will introduce you to more and more powerful tools -and advanced concepts. The more you know about Symfony, the more you'll -appreciate the flexibility of its architecture and the power it gives you -to rapidly develop applications. +Have fun! -.. _`Twig`: http://twig.sensiolabs.org -.. _`third-party bundles`: http://knpbundles.com -.. _`Symfony Standard Edition`: http://symfony.com/download -.. _`Apache's DirectoryIndex documentation`: http://httpd.apache.org/docs/current/mod/mod_dir.html -.. _`Nginx HttpCoreModule location documentation`: http://wiki.nginx.org/HttpCoreModule#location +.. _`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 diff --git a/book/templating.rst b/book/templating.rst index de6150764fd..9b426fa7c18 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -177,6 +177,8 @@ regenerate. Remember to do this when deploying your application. .. index:: single: Templating; Inheritance +.. _twig-inheritance: + Template Inheritance and Layouts -------------------------------- diff --git a/cookbook/configuration/web_server_configuration.rst b/cookbook/configuration/web_server_configuration.rst index f00c0a2fbae..0be18f40d31 100644 --- a/cookbook/configuration/web_server_configuration.rst +++ b/cookbook/configuration/web_server_configuration.rst @@ -19,7 +19,7 @@ to use PHP :ref:`with Nginx `. The web directory is the home of all of your application's public and static files, including images, stylesheets and JavaScript files. It is - also where the front controllers live. For more details, see the :ref:`the-web-directory`. + also where the front controllers (``app.php`` and ``app_dev.php``) live. The web directory serves as the document root when configuring your web server. In the examples below, the ``web/`` directory will be the