forked from nette/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap.texy
246 lines (167 loc) · 15.1 KB
/
bootstrap.texy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
Bootstrap
*********
<div class=perex>
Bootstrap — это загрузочный код, который инициализирует среду, создает контейнер внедрения зависимостей (DI) и запускает приложение. Мы обсудим:
- как настроить приложение с помощью файлов NEON
- как работать с режимами производства и разработки
- как создать контейнер DI
</div>
Приложения, будь то веб-приложения или скрипты командной строки, начинаются с инициализации среды в той или иной форме. В древние времена за это мог отвечать файл с именем, например, `include.inc.php`, который включался в исходный файл.
В современных приложениях Nette он заменен классом `Bootstrap`, который как часть приложения находится в файле `app/Bootstrap.php`. Это может выглядеть, например, так:
```php
use Nette\Bootstrap\Configurator;
class Bootstrap
{
public static function boot(): Configurator
{
$appDir = dirname(__DIR__);
$configurator = new Configurator;
//$configurator->setDebugMode('[email protected]');
$configurator->enableTracy($appDir . '/log');
$configurator->setTempDirectory($appDir . '/temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig($appDir . '/config/common.neon');
return $configurator;
}
}
```
index.php
=========
В случае веб-приложений начальным файлом является `index.php`, который находится в общедоступном каталоге `www/`. Он позволяет классу `Bootstrap` инициализировать среду и возвращает `$configurator`, который создает контейнер DI. Затем он получает сервис `Application`, запускающий веб-приложение:
```php
// инициализируем среду + получаем объект Configurator
$configurator = App\Bootstrap::boot();
// создаем DI-контейнер
$container = $configurator->createContainer();
// DI-контейнер создайет объект Nette\Application\Application
$application = $container->getByType(Nette\Application\Application::class);
// запускаем приложение Nette
$application->run();
```
Как вы видите, класс [api:Nette\Bootstrap\Configurator], который мы сейчас представим более подробно, помогает в настройке окружения и создании контейнера внедрения зависимостей (DI).
Режим разработки и режим производства .[#toc-development-vs-production-mode]
============================================================================
Nette различает два основных режима, в которых выполняется запрос: разработка и производство. Режим разработки ориентирован на максимальное удобство программиста, отображается Tracy, кэш автоматически обновляется при изменении шаблонов или конфигурации DI контейнера и т. д. Режим производства ориентирован на производительность, Tracy только регистрирует ошибки, а изменения шаблонов и других файлов не проверяются.
Выбор режима осуществляется путем автоопределения, поэтому обычно нет необходимости настраивать или переключать что-либо вручную. Режим разработки используется, если приложение запущено на localhost (т. е. IP-адрес `127.0.0.1` или `::1`) и отсутствует прокси-сервер (т. е. его HTTP-заголовок). В противном случае приложение работает в производственном режиме.
Если вы хотите включить режим разработки в других случаях, например, для программистов, получающих доступ с определенного IP-адреса, вы можете использовать `setDebugMode()`:
```php
$configurator->setDebugMode('23.75.345.200'); // один или более IP-адресов
```
Мы определенно рекомендуем сочетать IP-адрес с файлом cookie. Мы будем хранить секретный токен в cookie `nette-debug', например, `secret1234`, и режим разработки будет активирован для программистов с такой комбинацией IP и cookie.
```php
$configurator->setDebugMode('[email protected]');
```
Можно полностью отключить режим разработчика, даже для localhost:
```php
$configurator->setDebugMode(false);
```
Обратите внимание, что значение `true` жестко включает режим разработчика, чего никогда не должно происходить на рабочем сервере.
Отладочный инструмент Tracy .[#toc-debugging-tool-tracy]
========================================================
Для облегчения отладки мы включим замечательный инструмент [Tracy |tracy:]. В режиме разработчика он визуализирует ошибки, а в режиме производства — записывает ошибки в указанный каталог:
```php
$configurator->enableTracy($appDir . '/log');
```
Временные файлы .[#toc-temporary-files]
=======================================
Nette использует кэш для DI-контейнера, RobotLoader, шаблонов и т. д. Поэтому необходимо задать путь к директории, где будет храниться кэш:
```php
$configurator->setTempDirectory($appDir . '/temp');
```
В Linux или macOS установите [права на запись |nette:troubleshooting#Setting-Directory-Permissions] для каталогов `log/` и `temp/`.
RobotLoader
===========
Обычно мы хотим автоматически загружать классы с помощью [RobotLoader |robot-loader:], поэтому мы должны запустить его и позволить ему загрузить классы из каталога, в котором находится `Bootstrap.php` (т. е. `__DIR__`) и все его подкаталоги:
```php
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
```
Альтернативный способ — использовать только автозагрузку PSR-4 [Composer |best-practices:composer].
Часовой пояс .[#toc-timezone]
=============================
Configurator позволяет указать часовой пояс для вашего приложения.
```php
$configurator->setTimeZone('Europe/Prague');
```
Конфигурация DI-контейнера .[#toc-di-container-configuration]
=============================================================
Частью процесса загрузки является создание DI-контейнера, то есть фабрики объектов, которая является сердцем всего приложения. На самом деле это PHP-класс, созданный Nette и хранящийся в каталоге кэша. Фабрика создает ключевые объекты приложения, а конфигурационные файлы инструктируют её, как их создавать и настраивать, и таким образом мы влияем на поведение всего приложения.
Файлы конфигурации обычно записываются в формате [NEON|neon:format]. Вы можете прочитать [что можно настроить здесь|nette:configuring].
.[tip]
В режиме разработки контейнер автоматически обновляется каждый раз, когда вы изменяете код или конфигурационные файлы. В производственном режиме он генерируется только один раз, а изменения файлов не проверяются для достижения максимальной производительности.
Файлы конфигурации загружаются с помощью `addConfig()`:
```php
$configurator->addConfig($appDir . '/config/common.neon');
```
Метод `addConfig()` может быть вызван несколько раз для добавления нескольких файлов.
```php
$configurator->addConfig($appDir . '/config/common.neon');
$configurator->addConfig($appDir . '/config/local.neon');
if (PHP_SAPI === 'cli') {
$configurator->addConfig($appDir . '/config/cli.php');
}
```
Подключение `cli.php` не является опечаткой, конфигурация также может быть записана в PHP-файле, который возвращает ее в виде массива.
Альтернативно, мы можем использовать [секцию `includes`|dependency-injection:configuration#Including-Files] для загрузки конфигурационных файлов.
Если элементы с одинаковыми ключами отображаются в файлах конфигурации, они будут [перезаписаны или объединены |dependency-injection:configuration#Merging] в случае массивов. Позже включенный файл имеет более высокий приоритет, чем предыдущие. Файл, указанный в секции `includes`, имеет более высокий приоритет, чем файлы, включенные в него.
Статические параметры .[#toc-static-parameters]
-----------------------------------------------
Параметры, используемые в файлах конфигурации, могут быть определены [в секции `parameters`|dependency-injection:configuration#parameters] и подхвачены (или перезаписаны) методом `addStaticParameters()` (у него есть алиас `addParameters()`). Важно, что разные значения параметров вызывают генерацию дополнительных DI-контейнеров, то есть дополнительных классов.
```php
$configurator->addStaticParameters([
'projectId' => 23,
]);
```
В конфигурационных файлах мы можем написать обычную нотацию `%projectId%` для доступа к параметру с именем `projectId`.
Динамические параметры .[#toc-dynamic-parameters]
-------------------------------------------------
Можно также добавить динамические параметры в контейнер. Их разные значения, в отличие от статических параметров, не приведут к генерации новых DI-контейнеров.
```php
$configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
```
Переменные среды могут быть легко доступны с использованием динамических параметров. Мы можем получить доступ к ним через `%env.variable%` в файлах конфигурации.
```php
$configurator->addDynamicParameters([
'env' => getenv(),
]);
```
Параметры по умолчанию .[#toc-default-parameters]
-------------------------------------------------
Вы можете использовать следующие статические параметры в конфигурационных файлах:
- `%appDir%` - абсолютный путь к директории, содержащей файл `Bootstrap.php`.
- `%wwwDir%` - абсолютный путь к директории, содержащей входной файл `index.php`
- `%tempDir%` - абсолютный путь к директории для временных файлов.
- `%vendorDir%` - абсолютный путь к директории, в которую Composer устанавливает библиотеки.
- `%debugMode%` указывает, находится ли приложение в режиме отладки
- `%consoleMode%` указывает, поступил ли запрос через командную строку
Импортированные сервисы .[#toc-imported-services]
-------------------------------------------------
Углубимся дальше. Хотя цель DI-контейнера в создании объектов, может возникнуть необходимость вставить существующий объект в контейнер. Это делается определением сервиса с атрибутом `imported: true`:
```neon
services:
myservice:
type: App\Model\MyCustomService
imported: true
```
Создаём новый экземпляр и вставляем его в Bootstrap:
```php
$configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
```
Разные среды .[#toc-different-environments]
===========================================
Не стесняйтесь настроить класс `Bootstrap` в соответствии с вашими потребностями. Вы можете добавлять параметры в метод `boot()` для разделения веб-проектов, или добавлять другие методы, такие как `bootForTests()`, которые инициализируют среду для модульных тестов, `bootForCli()` для скриптов, вызываемых из командной строки, и так далее.
```php
public static function bootForTests(): Configurator
{
$configurator = self::boot();
Tester\Environment::setup(); // Инициализация Nette Tester
return $configurator;
}
```