diff --git a/book/app_structure.rst b/book/app_structure.rst new file mode 100644 index 00000000000..2aa84cb8a20 --- /dev/null +++ b/book/app_structure.rst @@ -0,0 +1,601 @@ +.. index:: + single: Structuring Apps in Symfony + +.. _structuring-apps-in-symfony2: + +Structuring Apps in Symfony +========================= + +The Directory Structure +----------------------- + +The short sections above illustrate several important principles behind +creating and rendering pages in Symfony. They also give an initial insight into +how Symfony projects are structured and organized by default. Each Symfony +:term:`application` has the same basic and recommended directory structure: + +``app/`` + This directory contains the application configuration, templates and stylesheets. + +``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:: + + For further important information on the directory structure, see + :doc:`/best_practices/creating-the-project.html#structuring-the-application`. + + +The Bundle System +----------------- + +Before you begin building apps, you'll need to create a *bundle*. In Symfony, a :term:`bundle` +is like a plugin, except that all of the code in your application will live +inside a bundle. + +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`). + + +To create a bundle called ``AcmeDemoBundle`` (an example bundle that you'll +build in this chapter), run the following command and follow the on-screen +instructions (use all of the default options): + +.. code-block:: bash + + $ php app/console generate:bundle --namespace=Acme/DemoBundle --format=yml + +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:: + + // app/AppKernel.php + public function registerBundles() + { + $bundles = array( + ..., + new Acme\DemoBundle\AcmeDemoBundle(), + ); + // ... + + return $bundles; + } + +Now that you have a bundle set up, you can begin building your application +inside the bundle. + +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 might create a ``BlogBundle``, a ``ForumBundle`` or a bundle for user management +(many of these exist already as open source bundles). Each directory contains all the +business logic related to that feature, including tests. Every feature lives in its +own bundle, along with every fundamental piece that should ship with that feature. + +An application is made up of bundles as defined 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(), + ); + + 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 $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 bundles + 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 with 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. + +Application Configuration +------------------------- + +An application consists of a collection of bundles representing all of 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: Page creation; Environments & Front Controllers + +.. _page-creation-environments: + +Environments & Front Controllers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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. + +.. _book-page-creation-prod-cache-clear: + +.. tip:: + + You can also view your app in the "prod" :ref:`environment ` + by visiting: + + .. code-block:: text + + http://localhost/app.php/random/10 + + If you get an error, it's likely because you need to clear your cache + by running: + + .. code-block:: bash + + $ php app/console cache:clear --env=prod --no-debug + +.. index:: + single: Environments; Introduction + +.. _environments-summary: + +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. + +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 four-step process involving a **bundle**, 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); + +* Each feature in Symfony (including the Symfony framework core) is organized + into a *bundle*, which is a structured set of files for that feature; + +* The **configuration** for each bundle lives in the ``Resources/config`` + directory of the bundle and can be specified in YAML, XML or PHP; + +* The global **application configuration** lives in the ``app/config`` + directory; + +* Each **environment** is accessible via a different front controller (e.g. + ``app.php`` and ``app_dev.php``) and loads a different configuration file. + +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. + +.. _`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 diff --git a/book/index.rst b/book/index.rst index 915b0fc7a7f..d7b840d99be 100644 --- a/book/index.rst +++ b/book/index.rst @@ -8,6 +8,7 @@ The Book from_flat_php_to_symfony2 installation page_creation + app_structure controller routing templating diff --git a/book/map.rst.inc b/book/map.rst.inc index 573c8027524..853a3587063 100644 --- a/book/map.rst.inc +++ b/book/map.rst.inc @@ -2,6 +2,7 @@ * :doc:`/book/from_flat_php_to_symfony2` * :doc:`/book/installation` * :doc:`/book/page_creation` +* :doc:`/book/app_structure` * :doc:`/book/controller` * :doc:`/book/routing` * :doc:`/book/templating` diff --git a/book/page_creation.rst b/book/page_creation.rst index cf8ca140e58..fb0df633dbb 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -6,7 +6,11 @@ Creating Pages in Symfony ========================= -Creating a new page in Symfony is a simple two-step process: +Creating a new page in Symfony is a simple three-step process, and the first +one is already done for you if you just installed Symfony's standard edition: + +* *Create a bundle*: A bundle is a structured set of files within a directory + that implement a single feature. Each bundle is registered with the kernel; * *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 @@ -16,50 +20,14 @@ Creating a new page in Symfony is a simple two-step process: request and transforms it into the Symfony ``Response`` object that's returned to the user. -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. +There is a beautiful simplicity in this approach based on routers and controllers. +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. -.. index:: - single: Page creation; Environments & Front Controllers - -.. _page-creation-environments: - -Environments & Front Controllers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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. - .. index:: single: Page creation; Example @@ -89,51 +57,23 @@ process. * For Apache HTTP Server, refer to `Apache's DirectoryIndex documentation`_ * For Nginx, refer to `Nginx HttpCoreModule location documentation`_ -Before you begin: Create the Bundle +Step 1: Create the Bundle ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Before you begin, you'll need to create a *bundle*. In Symfony, a :term:`bundle` -is like a plugin, except that all of the code in your application will live -inside a bundle. - -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`). +You probably already have a bundle called ``AcmeDemoBundle``; it is included when +you install Symfony's standard edition. -Depending on the way you installed Symfony, you may already have a bundle called -``AcmeDemoBundle``. Browse the ``src/`` directory of your project and check +To confirm it is there, 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. - -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 of the default options): - -.. code-block:: bash - - $ php app/console generate:bundle --namespace=Acme/DemoBundle --format=yml - -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:: +directories already exist, you're ready to create the route. If not, take a moment +to create one now. - // app/AppKernel.php - public function registerBundles() - { - $bundles = array( - ..., - new Acme\DemoBundle\AcmeDemoBundle(), - ); - // ... - - return $bundles; - } +.. seealso:: -Now that you have a bundle setup, you can begin building your application -inside the bundle. + For information about bundles, including quick steps to create a sample bundle, + see :doc:`/book/app_structure#the-bundle-system`. -Step 1: Create the Route +Step 2: Create the Route ~~~~~~~~~~~~~~~~~~~~~~~~ By default, the routing configuration file in a Symfony application is @@ -244,7 +184,7 @@ to generate the proper random number. and powerful URL structures in your application. For more details, see the chapter all about :doc:`Routing `. -Step 2: Create the Controller +Step 3: Create the Controller ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When a URL such as ``/random/10`` is handled by the application, the ``random`` @@ -298,38 +238,21 @@ application should generate a random number for you: 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: - - .. code-block:: text - - http://localhost/app.php/random/10 - - If you get an error, it's likely because you need to clear your cache - by running: - - .. code-block:: bash - - $ php app/console cache:clear --env=prod --no-debug - -An optional, but common, third step in the process is to create a template. - .. note:: 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 `. -Optional Step 3: Create the Template +Optional Step 4: Create the Template ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Templates allow you to move all of the presentation (e.g. HTML code) into -a separate file and reuse different portions of the page layout. Instead -of writing the HTML inside the controller, render a template instead: +An optional, but common, fourth step in the basic page-creation process is to +build a template. + +Templates allow you to move all of the presentation (e.g. HTML, XML, CSV, +LaTeX ...) into a separate file and reuse different portions of the page +layout. Rather than writing the HTML inside the controller, render a template: .. code-block:: php :linenos: @@ -473,625 +396,3 @@ 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 of 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 `. - -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. - -An application is made up of bundles as defined 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(), - ); - - 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 $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 bundles - 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 with 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. - -Application Configuration -------------------------- - -An application consists of a collection of bundles representing all of 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: - -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. - -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); - -* Each feature in Symfony (including the Symfony framework core) is organized - into a *bundle*, which is a structured set of files for that feature; - -* The **configuration** for each bundle lives in the ``Resources/config`` - directory of the bundle and can be specified in YAML, XML or PHP; - -* The global **application configuration** lives in the ``app/config`` - directory; - -* Each **environment** is accessible via a different front controller (e.g. - ``app.php`` and ``app_dev.php``) and loads a different configuration file. - -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. - -.. _`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