Skip to content

Add a section on front controllers and the AppKernel #2465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions cookbook/configuration/front_controllers_and_kernel.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
.. index::
single: How front controller, ``AppKernel`` and environments
work together

Understanding how Front Controller, Kernel and Environments work together
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are missing an .. index:: block at the first line of your page

=========================================================================

The section :doc:`/cookbook/configuration/environments`
explained the basics on how Symfony uses environments to run your
application with different configuration settings. This section will
explain a bit more in-depth what happens when your application is
bootstrapped. To hook into this process, you need to understand three
parts that work together:

* The front controller
* The ``Kernel` class
* The environment

.. note::

Usually, you will not need to define your own front controller or
``AppKernel`` as the `Symfony 2 Standard Edition`_ provides
sensible default implementations.

This documentation section is provided for completeness to
explain what is going on behind the scenes.


The front controller
====================

The `front controller`_ is a well-known design pattern; it is a
section of code that *all* requests served by an application run
through.

In the `Symfony 2 Standard Edition`_, this role is taken by the
``app.php``_ and ``app_dev.php``_ files in the ``web/`` directory.
These are the very first PHP scripts executed when a request is
processed.

The main purpose of the front controller is to create an instance of the
``AppKernel`` (more on that in a second), make it handle the request
and return the resulting response to the browser.

Because every request is routed through it, the front controller can be
used to perform global initializations prior to setting up the kernel or
to *`decorate`_* the kernel with additional features. Examples include:

* Configure the autoloader or add additional autoloading mechanisms
* Add HTTP level caching by wrapping the kernel with an instance of
:doc:`AppCache</book/http_cache#symfony2-reverse-proxy>`
* Enabling the `Debug component`_

When using Apache and the `RewriteRule shipped with the
Standard Edition`_, the front controller can be chosen by requesting
URLs like::

.. code-block:: text

http://localhost/app_dev.php/some/path/...

As you can see, this URL contains the PHP script to be used as
the front controller. You can use that to easily switch the front
controller or use a custom one by placing it in the ``web/`` directory.
If the front controller file is missing from the URL, the RewriteRule
will use ``app.php`` as the default one.

.. note::

Pretty much every other web server should be able to achieve a
behavior similar to that of the RewriteRule described above.
Check your server documentation for details.

.. note::

Make sure you appropriately
secure your front controllers against unauthorized access.

For example, you don't want to make a debugging environment
available to arbitraty users in your production environment.

Technically, the ``app/console``_ used when running
Symfony on the command line is also a front controller,
only that is not used for web, but for command line requests.

The ``AppKernel``
=================

The :class:`Symfony\\Component\\HttpKernel\\Kernel` is the core of
Symfony2. It is responsible for setting up all the bundles that make up
your application and providing them with the application's
configuration. It then creates the service container before serving
requests in its
:method:`Symfony\\Component\\HttpKernel\\HttpKernelInterface::handle`
method.

There are two methods declared in the
:class:`Symfony\\Component\\HttpKernel\\KernelInterface` that are
left unimplemented in :class:`Symfony\\Component\\HttpKernel\\Kernel`
and thus serve as `template methods`_:

* :method:`Symfony\\Component\\HttpKernel\\KernelInterface::registerBundles`,
which must return an array of all bundles needed to run the
application;

* :method:`Symfony\\Component\\HttpKernel\\KernelInterface::registerContainerConfiguration`,
which loads the application configuration.

To fill these (small) blanks, your application needs to subclass the
Kernel and implement these methods. The resulting class is
conventionally called the ``AppKernel``.

Again, the Symfony2 Standard Edition provides an `AppKernel`_ in
the
``app/`` directory. This class
uses the name of the environment, which is passed to the Kernel's
:method:`constructor<Symfony\\Component\\HttpKernel\\Kernel::__construct>`
and is available via
:method:`Symfony\\Component\\HttpKernel\\Kernel::getEnvironment`,
to decide which bundles to create. The logic for that is in
``registerBundles()``, a method meant to be extended by you when you
start adding bundles to your application.

You are, of course, free to create your own, alternative or additional
``AppKernel`` variants. All you need is to adapt your (or add a new) front
controller to make use of the new kernel.

.. note::

The name and location of the ``AppKernel`` is not fixed. When
putting multiple Kernels into a single application,
it might therefore make sense to add additional sub-directories,
for example ``app/admin/AdminKernel.php`` and
``app/api/ApiKernel.php``. All that matters is that your front
controller is able to create an instance of the appropriate
kernel.

Having different ``AppKernels`` might be useful to enable different
front controllers (on potentially different servers) to run parts of
your application independently (for example, the admin UI,
the frontend UI and database migrations).

.. note::

There's a lot more the ``AppKernel`` can be used for,
for example :doc:`overriding the default
directory structure
</cookbook/configuration /override_dir_structure>`. But odds are
high that you don't need to change such things on the fly by
having several ``AppKernel`` implementations at hand.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabling different front controllers on different servers in order to deploy or scale specifically functionality independently (f.e. admin UI, frontend UI, database migrations, REST API)

The environments
================

We just mentioned another method the ``AppKernel`` has to implement -
:method:`Symfony\\Component\\HttpKernel\\KernelInterface::registerContainerConfiguration`.
This method is responsible for loading the application's
configuration from the right *environment*.

Environments have been covered extensively
:doc:`in the previous chapter</cookbook/configuration/environments>`,
and you probably remember that the Standard Edition comes with three
of them - ``dev``, ``prod`` and ``test``.

More technically, these names are nothing more than strings passed
from the front controller to the ``AppKernel``'s constructor. This
name can then be used in
:method:`Symfony\\Component\\HttpKernel\\KernelInterface::registerContainerConfiguration`
method to decide which configuration files to load.

The Standard
Edition's ``AppKernel``_ class implements this method by
simply loading the ``app/config/config_*environment*.yml`` file. You
are, of course, free to implement this method differently if you need
a more sophisticated way of loading your configuration.

.. _front controller: http://en.wikipedia.org/wiki/Front_Controller_pattern
.. _Symfony 2 Standard Edition: https://github.com/symfony/symfony-standard
.. _app.php: https://github.com/symfony/symfony-standard/blob/master/web/app.php
.. _app_dev.php: https://github.com/symfony/symfony-standard/blob/master/web/app_dev.php
.. _app/console: https://github.com/symfony/symfony-standard/blob/master/app/console
.. _AppKernel: https://github.com/symfony/symfony-standard/blob/master/app/AppKernel.php
.. _decorate: http://en.wikipedia.org/wiki/Decorator_pattern
.. _Debug Component: https://github.com/symfony/symfony/pull/7441
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's an interesting feature and worth mentioning once it gets merged. How can we make sure it will be reflected then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be documented only once the component is merged, and not with a link to the PR adding it but to the component documentation (which will need to be written first)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but how can we make sure now that we don't forget to add it here once it becomes ready?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mpdude I've put it on my doc watch list, as soon as we have documentation, I create a PR adding it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thus, keeping this unused link here would not ensure we don't forget it.

.. _RewriteRule shipped with the Standard Edition: https://github.com/symfony/symfony-standard/blob/master/web/.htaccess)
.. _template methods: http://en.wikipedia.org/wiki/Template_method_pattern
1 change: 1 addition & 0 deletions cookbook/configuration/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Configuration
:maxdepth: 2

environments
front_controllers_and_kernel
override_dir_structure
external_parameters
pdo_session_storage
Expand Down