Bootstrap

Nette application is easily configured using NEON files. We'll talk about:

  • how to configure your application using NEON files
  • how to handle production and development modes
  • how to create the DI container

In charge of setting up the environment and creating a Dependency Injection (DI) container in Nette is the Configurator class. It is used in the bootstrap file bootstrap.php located in the app/ folder.

Development Mode

Development mode is automatically enabled when we're running on localhost. If you want to enable it even outside of there, for example, programmers accessing from a specific IP address, you can use setDebugMode():

$configurator->setDebugMode('23.75.345.200'); // one or more IP addresses

Even more secure is the combination of an IP address and a cookie. We will store a secret token into the nette-debug' cookie, e.g. `secret1234, and the development mode will be activated for programmers with this combination of IP and cookie.

$configurator->setDebugMode('secret1234@23.75.345.200');

The development mode can be deactivated by:

$configurator->setDebugMode(false);

Debugging Tool Tracy

Turn on the great debugging tool Tracy, it'll store all exceptions into files in a specified folder (__DIR__ . '/../log').

$configurator->enableTracy(__DIR__ . '/../log');

Caching

The configuration is loaded and processed only once, and the result is cached, which greatly speeds up the application. Therefore, we set the setTempDirectory() path where the cache will be saved.

$configurator->setTempDirectory(__DIR__ . '/../temp');

RobotLoader

Usually we will want to automatically load the classes using RobotLoader, so we have to start it up and let it load classes from the directory where bootstrap.php is located and all its subdirectories (i.e. __DIR__):

$configurator->createRobotLoader()
    ->addDirectory(__DIR__)
    ->register();

An alternative way is to only use Composer PSR-4 autoloading.

Timezone

Configurator allows you to specify a timezone for your application.

$configurator->setTimeZone('Europe/Prague');

Configuration Files

Typically, configuration files are written in the NEON format. Based on the configuration files, a system DI container is generated. This is the heart of the entire application. In a separate chapter, you can read everything about configuration.

We load the configuration files using addConfig():

$configurator->addConfig(__DIR__ . '/config/config.neon');

The method addConfig() can be called multiple times to add multiple files.

$configurator->addConfig(__DIR__ . '/config/common.neon');
$configurator->addConfig(__DIR__ . '/config/local.neon');
if (PHP_SAPI === 'cli') {
    $configurator->addConfig(__DIR__ . '/config/cli.neon');
}

Alternatively we can use the includes section to load more configuration files.

includes:
    - parameters.php
    - services.neon
    - presenters.neon

If items with the same keys appear within configuration files, they will be overwritten, or merged in the case of arrays. Each subsequent file has a higher priority in merging. The file containing the includes section has a higher priority than the included files.

Parameters

Parameters can be passed to the DI container by the addParameters() method; their values must be known at compile time. The container is always generated for the different values of these parameters.

$configurator->addParameters([
    'foo' => 'bar',
    'baz' => '%tempDir%',
]);

In configuration files, we can write %foo% to access the parameter named foo. By default, the Configurator populates the following parameters: appDir, wwwDir, tempDir, debugMode and consoleMode.

Dynamic Parameters

We can also feed dynamic parameters to the DI container. Their values needn't be known at compile time: they are used at run time. Different values don't regenerate the container.

$configurator->addDynamicParameters([
    'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);

Environment variables could be easily made available using dynamic parameters. We can access them via %env.variable% in configuration files.

$configurator->addDynamicParameters([
    'env' => $_ENV,
]);

Dynamic Services

We can insert an instance of a class into the DI container directly, before the DI container creates it for us. The service must be defined with the dynamic: true attribute.

services:
    myservice:
        class: App\Model\MyCustomService
        dynamic: true

Create a new instance and insert it in bootstrap:

$configurator->addServices([
    'myservice' => new App\Model\MyCustomService('foobar'),
]);

Creating a Container

The method createContainer() generates the container class and returns its instance:

/** @var Nette\DI\Container $container */
$container = $configurator->createContainer();

In the development mode, the container is automatically updated each time you change the code or configuration files. In production mode, it is generated only once and file changes are not checked to avoid compromising performance.

index.php

If we are creating a web application, all requests are handled by one file located in the public www/ directory, and that is index.php. It just passes the control to the application (that is the app/ directory), to the bootstrap file bootstrap.php. Subsequently, index.php retrieves from the DI container the service that runs the web application:

$container = require __DIR__ . '/../app/bootstrap.php';
$container->getByType(Nette\Application\Application::class)
    ->run();