|
| 1 | +.. index:: |
| 2 | + single: kernel, performance |
| 3 | + |
| 4 | +How To Create Symfony Applications with Multiple Kernels |
| 5 | +======================================================== |
| 6 | + |
| 7 | +In most Symfony applications, incoming requests are processed by the |
| 8 | +``web/app.php`` front controller, which instantiates the ``app/AppKernel.php`` |
| 9 | +class to create the application kernel that loads the bundles and generates the |
| 10 | +response. |
| 11 | + |
| 12 | +This single kernel approach is a convenient default provided by the Symfony |
| 13 | +Standard edition, but Symfony applications can define any number of kernels. |
| 14 | +This is useful to execute the same application using a different configuration |
| 15 | +and a different set of bundles for each kernel: |
| 16 | + |
| 17 | +* An application that defines an API could create an ``ApiKernel`` to not have |
| 18 | + to load all the bundles enabled in the regular web application. This will |
| 19 | + improve the API performance; |
| 20 | +* A bundle that doesn't allow multiple instances can define multiple |
| 21 | + configurations in different files loaded by each kernel. |
| 22 | + |
| 23 | +Adding a new Kernel to the Application |
| 24 | +-------------------------------------- |
| 25 | + |
| 26 | +Creating a new kernel in a Symfony application is a three-step process: |
| 27 | + |
| 28 | +1. Create a new front controller to load the new kernel; |
| 29 | +2. Create the new kernel class; |
| 30 | +3. Define the configuration loaded by the new kernel. |
| 31 | + |
| 32 | +The following example shows how to create a new kernel for the API of a given |
| 33 | +Symfony application. |
| 34 | + |
| 35 | +Step 1) Create a new Front Controller |
| 36 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 37 | + |
| 38 | +Instead of creating the new front controller from scratch, it's recommended to |
| 39 | +duplicate the existing ``web/app_dev.php`` and ``web/app.php`` files. For |
| 40 | +example, you can create ``web/api_dev.php`` and ``web/api.php`` (or |
| 41 | +``web/api/app_dev.php`` and ``web/api/app.php`` depending on your server |
| 42 | +configuration). |
| 43 | + |
| 44 | +Then, update the code of the new front controllers to instantiate the new kernel |
| 45 | +class instead of the usual ``AppKernel`` class: |
| 46 | + |
| 47 | + // web/api.php |
| 48 | + // ... |
| 49 | + $kernel = new ApiKernel('prod', true); |
| 50 | + // ... |
| 51 | + |
| 52 | + // web/api_dev.php |
| 53 | + // ... |
| 54 | + $kernel = new ApiKernel('dev', true); |
| 55 | + // ... |
| 56 | + |
| 57 | +Step 2) Create the new Kernel Class |
| 58 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 59 | + |
| 60 | +Now you need to define the ``ApiKernel`` class used by the new front controller. |
| 61 | +The recommendation again is to duplicate the existing ``app/AppKernel.php`` file |
| 62 | +and make the needed changes. |
| 63 | + |
| 64 | +In this example, the changes of the new ``ApiKernel`` would be to load less |
| 65 | +bundles than ``AppKernel`` and to change the location of the cache, logs and |
| 66 | +config files to not mess with the regular application: |
| 67 | + |
| 68 | + // app/ApiKernel.php |
| 69 | + <?php |
| 70 | + |
| 71 | + use Symfony\Component\HttpKernel\Kernel; |
| 72 | + use Symfony\Component\Config\Loader\LoaderInterface; |
| 73 | + |
| 74 | + class ApiKernel extends Kernel |
| 75 | + { |
| 76 | + public function registerBundles() |
| 77 | + { |
| 78 | + // load only the bundles strictly needed for the API... |
| 79 | + } |
| 80 | + |
| 81 | + public function getCacheDir() |
| 82 | + { |
| 83 | + return dirname(__DIR__).'/var/cache/api/'.$this->getEnvironment(); |
| 84 | + } |
| 85 | + |
| 86 | + public function getLogDir() |
| 87 | + { |
| 88 | + return dirname(__DIR__).'/var/logs/api'; |
| 89 | + } |
| 90 | + |
| 91 | + public function registerContainerConfiguration(LoaderInterface $loader) |
| 92 | + { |
| 93 | + $loader->load($this->getRootDir().'/config/api/config_'.$this->getEnvironment().'.yml'); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | +Step 3) Define the Kernel Configuration |
| 98 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 99 | + |
| 100 | +Finally, define the configuration used by the application when it executes the |
| 101 | +new API kernel. According to the previous code, this config must be defined in |
| 102 | +the ``app/config/api/`` directory. |
| 103 | + |
| 104 | +The new configuration can be created from scratch when you load just a few |
| 105 | +bundles, because it it will be very simple. Otherwise, duplicate the existing |
| 106 | +config files or better, import them and override the needed options: |
| 107 | + |
| 108 | +.. code-block:: yaml |
| 109 | +
|
| 110 | + # app/config/api/config_dev.yml |
| 111 | + imports: |
| 112 | + - { resource: ../config_dev.yml } |
| 113 | +
|
| 114 | + # override option values ... |
| 115 | +
|
| 116 | +Adding more Kernels to the Application |
| 117 | +-------------------------------------- |
| 118 | + |
| 119 | +If your application is very complex and you create several kernels, it's better |
| 120 | +to store them on their own directories instead of messing with lots of files in |
| 121 | +the default ``app/`` directory: |
| 122 | + |
| 123 | +.. code-block:: text |
| 124 | +
|
| 125 | + project/ |
| 126 | + ├─ app/ |
| 127 | + │ ├─ ... |
| 128 | + │ ├─ config/ |
| 129 | + │ └─ AppKernel.php |
| 130 | + ├─ api/ |
| 131 | + │ ├─ ... |
| 132 | + │ ├─ config/ |
| 133 | + │ └─ ApiKernel.php |
| 134 | + ├─ ... |
| 135 | + └─ web/ |
| 136 | + ├─ ... |
| 137 | + ├─ app.php |
| 138 | + ├─ app_dev.php |
| 139 | + ├─ api.php |
| 140 | + └─ api_dev.php |
0 commit comments