/
bootstrap.texy
247 lines (168 loc) · 11.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
247
Bootstrap
*********
<div class=perex>
A Bootstrap egy indító kód, amely inicializálja a környezetet, létrehoz egy függőségi injektálási (DI) konténert, és elindítja az alkalmazást. Megbeszéljük:
- hogyan konfigurálhatja az alkalmazást NEON fájlok segítségével.
- hogyan kezelje a termelési és a fejlesztési módokat
- hogyan hozzuk létre a DI konténert
</div>
Az alkalmazások, akár webes alapúak, akár parancssori szkriptek, valamilyen környezet-inicializálással kezdődnek. A régi időkben ez egy pl. `include.inc.php` nevű fájl lehetett, amely ezért volt felelős, és a kezdeti fájlban szerepelt.
A modern Nette alkalmazásokban ezt felváltotta a `Bootstrap` osztály, amely az alkalmazás részeként a `app/Bootstrap.php`. Ez például így nézhet ki:
```php
use Nette\Bootstrap\Configurator;
class Bootstrap
{
public static function boot(): Configurator
{
$appDir = dirname(__DIR__);
$configurator = new Configurator;
//$configurator->setDebugMode('secret@23.75.345.200');
$configurator->enableTracy($appDir . '/log');
$configurator->setTempDirectory($appDir . '/temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig($appDir . '/config/common.neon');
return $configurator;
}
}
```
index.php .[#toc-index-php]
===========================
A webes alkalmazások esetében a kezdő fájl a `index.php`, amely a `www/` nyilvános könyvtárban található. Ez lehetővé teszi a `Bootstrap` osztály számára, hogy inicializálja a környezetet, és visszaadja a `$configurator`, amely létrehozza a DI konténert. Ezután megszerzi a `Application` szolgáltatást, amely a webalkalmazást futtatja:
```php
// a környezet inicializálása + konfigurátor objektum kinyerése
$configurator = App\Bootstrap::boot();
// DI konténer létrehozása
$container = $configurator->createContainer();
// A DI konténer létrehoz egy Nette\Application\Application objektumot.
$application = $container->getByType(Nette\Application\Application::class);
// Nette alkalmazás indítása
$application->run();
```
Mint látható, a [api:Nette\Bootstrap\Configurator] osztály, amelyet most részletesebben bemutatunk, segít a környezet beállításában és a függőségi injektálás (DI) konténer létrehozásában.
Fejlesztői vs. termelési üzemmód .[#toc-development-vs-production-mode]
=======================================================================
A Nette két alapvető módot különböztet meg, amelyben egy kérés végrehajtásra kerül: fejlesztési és termelési mód. A fejlesztési mód a programozó maximális kényelmére összpontosít, a Tracy megjelenik, a gyorsítótár automatikusan frissül, ha a sablonok vagy a DI konténer konfigurációja változik, stb. A termelési mód a teljesítményre összpontosít, a Tracy csak a hibákat naplózza, a sablonok és egyéb fájlok módosításait nem ellenőrzi.
A mód kiválasztása automatikus felismeréssel történik, így általában nem szükséges kézzel konfigurálni vagy váltani semmit. A mód fejlesztési, ha az alkalmazás localhoston fut (azaz a `127.0.0.1` vagy a `::1` IP-címen ) és nincs proxy (azaz a HTTP fejléce). Ellenkező esetben termelési üzemmódban fut.
Ha más esetekben, például egy adott IP-címről hozzáférő programozók számára szeretné engedélyezni a fejlesztési üzemmódot, akkor a `setDebugMode()` címet használhatja:
```php
$configurator->setDebugMode('23.75.345.200'); // egy vagy több IP-cím
```
Mindenképpen javasoljuk az IP-cím és a cookie kombinálását. A `nette-debug` cookie-ban tárolunk egy titkos tokent, pl. `secret1234`, és a fejlesztési mód az IP és a cookie ilyen kombinációjával rendelkező programozók számára aktiválódik.
```php
$configurator->setDebugMode('secret1234@23.75.345.200');
```
A fejlesztői módot teljesen ki is kapcsolhatjuk, akár a localhost esetében is:
```php
$configurator->setDebugMode(false);
```
A `true` érték keményen bekapcsolja a fejlesztői módot, ami soha nem történhet meg egy termelő szerveren.
Hibakereső eszköz Tracy .[#toc-debugging-tool-tracy]
====================================================
Az egyszerű hibakeresés érdekében bekapcsoljuk a [Tracy |tracy:] nevű nagyszerű eszközt. Fejlesztői módban megjeleníti a hibákat, termelési módban pedig a megadott könyvtárba naplózza a hibákat:
```php
$configurator->enableTracy($appDir . '/log');
```
Ideiglenes fájlok .[#toc-temporary-files]
=========================================
A Nette a DI konténer, a RobotLoader, a sablonok stb. számára használja a gyorsítótárat. Ezért szükséges annak a könyvtárnak az elérési útvonalát beállítani, ahol a gyorsítótár tárolásra kerül:
```php
$configurator->setTempDirectory($appDir . '/temp');
```
Linuxon vagy macOS-en állítsa be a `log/` és a `temp/` könyvtárak [írási engedélyeit |nette:troubleshooting#Setting directory permissions].
RobotLoader .[#toc-robotloader]
===============================
Általában a [RobotLoader |robot-loader:] segítségével szeretnénk automatikusan betölteni az osztályokat, ezért el kell indítanunk, és hagynunk kell, hogy betöltse az osztályokat abból a könyvtárból, ahol a `Bootstrap.php` található (azaz `__DIR__`) és annak összes alkönyvtárából:
```php
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
```
Egy alternatív megoldás az, hogy csak a [Composer |best-practices:composer] PSR-4 automatikus betöltését használjuk.
Időzóna .[#toc-timezone]
========================
A Configurator lehetővé teszi, hogy megadjon egy időzónát az alkalmazásához.
```php
$configurator->setTimeZone('Europe/Prague');
```
DI konténer konfigurálása .[#toc-di-container-configuration]
============================================================
Az indítási folyamat része a DI konténer, azaz az objektumgyár létrehozása, amely az egész alkalmazás szíve. Ez tulajdonképpen egy Nette által generált és egy cache könyvtárban tárolt PHP osztály. A gyár létrehozza az alkalmazás kulcsfontosságú objektumait, a konfigurációs fájlok pedig utasítják, hogyan hozza létre és konfigurálja őket, és így befolyásoljuk az egész alkalmazás viselkedését.
A konfigurációs fájlokat általában [NEON formátumban |neon:format] írjuk. Itt olvashatja el, hogy mit lehet [konfigurálni |nette:configuring].
.[tip]
Fejlesztői üzemmódban a konténer automatikusan frissül minden alkalommal, amikor megváltoztatja a kódot vagy a konfigurációs fájlokat. Termelési módban csak egyszer generálódik, és a teljesítmény maximalizálása érdekében a fájlváltozásokat nem ellenőrzi a rendszer.
A konfigurációs fájlok betöltése a `addConfig()` segítségével történik:
```php
$configurator->addConfig($appDir . '/config/common.neon');
```
A `addConfig()` metódus többször is meghívható több fájl hozzáadásához.
```php
$configurator->addConfig($appDir . '/config/common.neon');
$configurator->addConfig($appDir . '/config/services.neon');
if (PHP_SAPI === 'cli') {
$configurator->addConfig($appDir . '/config/cli.php');
}
```
A `cli.php` név nem elírás, a konfiguráció egy PHP fájlba is írható, amely tömbként adja vissza.
Alternatívaként használhatjuk a [`includes` szekciót |dependency-injection:configuration#including files] is, hogy több konfigurációs fájlt töltsünk be.
Ha a konfigurációs fájlokban azonos kulcsú elemek jelennek meg, akkor azok [felülíródnak, vagy |dependency-injection:configuration#Merging] tömbök esetén [összevonásra |dependency-injection:configuration#Merging] kerülnek. A később bevont fájlnak magasabb prioritása van, mint az előzőnek. Az a fájl, amelyben a `includes` szakasz szerepel, magasabb prioritással rendelkezik, mint a benne foglalt fájlok.
Statikus paraméterek .[#toc-static-parameters]
----------------------------------------------
A konfigurációs fájlokban használt paramétereket a [`parameters` szakaszban |dependency-injection:configuration#parameters] lehet definiálni, és a `addStaticParameters()` metódus (amelynek alias neve `addParameters()`) is átadhatja (vagy felülírhatja). Fontos, hogy a különböző paraméterértékek további DI-konténerek, azaz további osztályok generálását okozzák.
```php
$configurator->addStaticParameters([
'projectId' => 23,
]);
```
A konfigurációs fájlokban a `%projectId%` szokásos jelölést írhatjuk a `projectId` nevű paraméter eléréséhez.
Dinamikus paraméterek .[#toc-dynamic-parameters]
------------------------------------------------
A konténerhez dinamikus paramétereket is hozzáadhatunk, ezek eltérő értékei a statikus paraméterekkel ellentétben nem okoznak új DI-konténerek generálását.
```php
$configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
```
A környezeti változókat könnyen elérhetővé tehetnénk dinamikus paraméterek segítségével. A konfigurációs fájlokban a `%env.variable%` címen keresztül érhetjük el őket.
```php
$configurator->addDynamicParameters([
'env' => getenv(),
]);
```
Alapértelmezett paraméterek .[#toc-default-parameters]
------------------------------------------------------
A konfigurációs fájlokban a következő statikus paramétereket használhatja:
- `%appDir%` a `Bootstrap.php` fájl könyvtárának abszolút elérési útja.
- `%wwwDir%` a `index.php` beviteli fájlt tartalmazó könyvtár abszolút elérési útja.
- `%tempDir%` az ideiglenes fájlok könyvtárának abszolút elérési útja.
- `%vendorDir%` az abszolút elérési út a könyvtárak Composer általi telepítésének könyvtárához.
- `%rootDir%` a projekt gyökérkönyvtárának abszolút elérési útvonala.
- `%debugMode%` jelzi, hogy az alkalmazás hibakeresési módban van-e.
- `%consoleMode%` jelzi, hogy a kérés a parancssoron keresztül érkezett-e.
Importált szolgáltatások .[#toc-imported-services]
--------------------------------------------------
Most mélyebbre megyünk. Bár a DI konténer célja az objektumok létrehozása, kivételesen szükség lehet arra, hogy egy meglévő objektumot beillesszünk a konténerbe. Ezt úgy tesszük meg, hogy a szolgáltatást a `imported: true` attribútummal definiáljuk.
```neon
services:
myservice:
type: App\Model\MyCustomService
imported: true
```
Hozzunk létre egy új példányt, és illesszük be a bootstrapbe:
```php
$configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
```
Különböző környezetek .[#toc-different-environments]
====================================================
Nyugodtan testre szabhatja a `Bootstrap` osztályt, hogy megfeleljen az igényeinek. A `boot()` metódushoz paramétereket adhat a webes projektek megkülönböztetéséhez, vagy más metódusokat is hozzáadhat, például a `bootForTests()`, amely inicializálja a környezetet a unit tesztekhez, a `bootForCli()` a parancssorból hívott szkriptekhez, és így tovább.
```php
public static function bootForTests(): Configurator
{
$configurator = self::boot();
Tester\Environment::setup(); // Nette Tester inicializálása
return $configurator;
}
```