You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
msgid"There are two ways of re-using things in OOP: inheritance and composition."
34
34
msgstr""
35
35
36
36
#. type: Plain text
37
-
#: ../../guide/en/concept/di-container.md
37
+
#: ../src/guide/concept/di-container.md
38
38
msgid"Inheritance is simple:"
39
39
msgstr""
40
40
41
41
#. type: Fenced code block (php)
42
-
#: ../../guide/en/concept/di-container.md
42
+
#: ../src/guide/concept/di-container.md
43
43
#, no-wrap
44
44
msgid""
45
45
"class Cache\n"
@@ -64,17 +64,17 @@ msgid ""
64
64
msgstr""
65
65
66
66
#. type: Plain text
67
-
#: ../../guide/en/concept/di-container.md
67
+
#: ../src/guide/concept/di-container.md
68
68
msgid"The issue here is that these two are becoming unnecessarily coupled or inter-dependent, making them more fragile."
69
69
msgstr""
70
70
71
71
#. type: Plain text
72
-
#: ../../guide/en/concept/di-container.md
72
+
#: ../src/guide/concept/di-container.md
73
73
msgid"Another way to handle this is composition:"
74
74
msgstr""
75
75
76
76
#. type: Fenced code block (php)
77
-
#: ../../guide/en/concept/di-container.md
77
+
#: ../src/guide/concept/di-container.md
78
78
#, no-wrap
79
79
msgid""
80
80
"interface CacheInterface\n"
@@ -110,130 +110,138 @@ msgid ""
110
110
msgstr""
111
111
112
112
#. type: Plain text
113
-
#: ../../guide/en/concept/di-container.md
113
+
#: ../src/guide/concept/di-container.md
114
114
msgid"We've avoided unnecessary inheritance and used interface to reduce coupling. You can replace cache implementation without changing `CachedWidget` so it's becoming more stable."
115
115
msgstr""
116
116
117
117
#. type: Plain text
118
-
#: ../../guide/en/concept/di-container.md
118
+
#: ../src/guide/concept/di-container.md
119
119
msgid"The `CacheInterface` here is a dependency: an object another object depends on. The process of putting an instance of dependency into an object (`CachedWidget`) is called dependency injection. There are many ways to perform it:"
120
120
msgstr""
121
121
122
122
#. type: Bullet: '- '
123
-
#: ../../guide/en/concept/di-container.md
123
+
#: ../src/guide/concept/di-container.md
124
124
msgid"Constructor injection. Best for mandatory dependencies."
125
125
msgstr""
126
126
127
127
#. type: Bullet: '- '
128
-
#: ../../guide/en/concept/di-container.md
128
+
#: ../src/guide/concept/di-container.md
129
129
msgid"Method injection. Best for optional dependencies."
130
130
msgstr""
131
131
132
132
#. type: Bullet: '- '
133
-
#: ../../guide/en/concept/di-container.md
133
+
#: ../src/guide/concept/di-container.md
134
134
msgid"Property injection. Better to be avoided in PHP except maybe data transfer objects."
135
135
msgstr""
136
136
137
137
#. type: Title ###
138
-
#: ../../guide/en/concept/di-container.md
138
+
#: ../src/guide/concept/di-container.md
139
139
#, no-wrap
140
140
msgid"Why use private properties <span id=\"why-private-properties\"></span>"
141
141
msgstr""
142
142
143
143
#. type: Plain text
144
-
#: ../../guide/en/concept/di-container.md
144
+
#: ../src/guide/concept/di-container.md
145
145
msgid"In the composition example above, note that the `$cache` property is declared as `private`."
146
146
msgstr""
147
147
148
148
#. type: Plain text
149
-
#: ../../guide/en/concept/di-container.md
149
+
#: ../src/guide/concept/di-container.md
150
150
msgid"This approach embraces composition by ensuring objects have well-defined interfaces for interaction rather than direct property access, making the code more maintainable and less prone to certain types of mistakes."
151
151
msgstr""
152
152
153
153
#. type: Plain text
154
-
#: ../../guide/en/concept/di-container.md
154
+
#: ../src/guide/concept/di-container.md
155
155
msgid"This design choice provides several benefits:"
156
156
msgstr""
157
157
158
158
#. type: Bullet: '- '
159
-
#: ../../guide/en/concept/di-container.md
159
+
#: ../src/guide/concept/di-container.md
160
160
msgid"**Encapsulation**: Private properties with getters/setters allow you to control access and make future changes without breaking existing code."
161
161
msgstr""
162
162
163
163
#. type: Bullet: '- '
164
-
#: ../../guide/en/concept/di-container.md
164
+
#: ../src/guide/concept/di-container.md
165
165
msgid"**Data integrity**: Setters can validate, normalize, or format values before storing them, ensuring properties contain valid data."
166
166
msgstr""
167
167
168
168
#. type: Bullet: '- '
169
-
#: ../../guide/en/concept/di-container.md
169
+
#: ../src/guide/concept/di-container.md
170
170
msgid"**Immutability**: Private properties enable immutable object patterns where setter `with*()` methods return new instances rather than modifying the current one."
171
171
msgstr""
172
172
173
173
#. type: Bullet: '- '
174
-
#: ../../guide/en/concept/di-container.md
174
+
#: ../src/guide/concept/di-container.md
175
175
msgid"**Flexibility**: You can create read-only or write-only properties or add additional logic to property access later."
msgid"Injecting basic dependencies is straightforward. You're choosing a place where you don't care about dependencies, which is usually an action handler, which you aren't going to unit-test ever, create instances of dependencies needed and pass these to dependent classes."
187
187
msgstr""
188
188
189
189
#. type: Plain text
190
-
#: ../../guide/en/concept/di-container.md
190
+
#: ../src/guide/concept/di-container.md
191
191
msgid"It works well when there are few dependencies overall and when there are no nested dependencies. When there are many and each dependency has dependencies itself, instantiating the whole hierarchy becomes a tedious process, which requires lots of code and may lead to hardly debuggable mistakes."
192
192
msgstr""
193
193
194
194
#. type: Plain text
195
-
#: ../../guide/en/concept/di-container.md
195
+
#: ../src/guide/concept/di-container.md
196
196
msgid"Additionally, lots of dependencies, such as certain third-party API wrappers, are the same for any class using it. So it makes sense to:"
197
197
msgstr""
198
198
199
199
#. type: Bullet: '- '
200
-
#: ../../guide/en/concept/di-container.md
200
+
#: ../src/guide/concept/di-container.md
201
201
msgid"Define how to instantiate such an API wrapper."
202
202
msgstr""
203
203
204
204
#. type: Bullet: '- '
205
-
#: ../../guide/en/concept/di-container.md
205
+
#: ../src/guide/concept/di-container.md
206
206
msgid"Instantiate it when required and only once per request."
207
207
msgstr""
208
208
209
209
#. type: Plain text
210
-
#: ../../guide/en/concept/di-container.md
210
+
#: ../src/guide/concept/di-container.md
211
211
msgid"That's what dependency containers are for."
212
212
msgstr""
213
213
214
214
#. type: Plain text
215
-
#: ../../guide/en/concept/di-container.md
215
+
#: ../src/guide/concept/di-container.md
216
216
msgid"A dependency injection (DI) container is an object that knows how to instantiate and configure objects and all their dependent objects. [Martin Fowler's article](https://martinfowler.com/articles/injection.html) has well explained why DI container is useful. Here we will mainly explain the usage of the DI container provided by Yii."
217
217
msgstr""
218
218
219
219
#. type: Plain text
220
-
#: ../../guide/en/concept/di-container.md
220
+
#: ../src/guide/concept/di-container.md
221
+
#, no-wrap
222
+
msgid""
223
+
"> [!NOTE]\n"
224
+
"> The container contains only shared instances. If you need a factory, use the dedicated [yiisoft/factory](https://github.com/yiisoft/factory) package.\n"
225
+
msgstr""
226
+
227
+
#. type: Plain text
228
+
#: ../src/guide/concept/di-container.md
221
229
msgid"Yii provides the DI container feature through the [yiisoft/di](https://github.com/yiisoft/di) package and [yiisoft/injector](https://github.com/yiisoft/injector) package."
msgid"Because to create a new object you need its dependencies, you should register them as early as possible. You can do it in the application configuration, `config/web.php`. For the following service:"
233
241
msgstr""
234
242
235
243
#. type: Fenced code block (php)
236
-
#: ../../guide/en/concept/di-container.md
244
+
#: ../src/guide/concept/di-container.md
237
245
#, no-wrap
238
246
msgid""
239
247
"final class MyService implements MyServiceInterface\n"
@@ -250,12 +258,12 @@ msgid ""
250
258
msgstr""
251
259
252
260
#. type: Plain text
253
-
#: ../../guide/en/concept/di-container.md
261
+
#: ../src/guide/concept/di-container.md
254
262
msgid"configuration could be:"
255
263
msgstr""
256
264
257
265
#. type: Fenced code block (php)
258
-
#: ../../guide/en/concept/di-container.md
266
+
#: ../src/guide/concept/di-container.md
259
267
#, no-wrap
260
268
msgid""
261
269
"return [\n"
@@ -268,25 +276,25 @@ msgid ""
268
276
msgstr""
269
277
270
278
#. type: Plain text
271
-
#: ../../guide/en/concept/di-container.md
279
+
#: ../src/guide/concept/di-container.md
272
280
msgid"That's equal to the following:"
273
281
msgstr""
274
282
275
283
#. type: Fenced code block (php)
276
-
#: ../../guide/en/concept/di-container.md
284
+
#: ../src/guide/concept/di-container.md
277
285
#, no-wrap
278
286
msgid""
279
287
"$myService = new MyService(42);\n"
280
288
"$myService->setDiscount(10);\n"
281
289
msgstr""
282
290
283
291
#. type: Plain text
284
-
#: ../../guide/en/concept/di-container.md
292
+
#: ../src/guide/concept/di-container.md
285
293
msgid"There are extra methods of declaring dependencies:"
msgid"Directly referencing a container in a class is a bad idea since the code becomes non-generic, coupled to the container interface and, what's worse, dependencies are becoming hidden. Because of that, Yii inverts the control by automatically injecting objects from a container in some constructors and methods based on method argument types."
326
334
msgstr""
327
335
328
336
#. type: Plain text
329
-
#: ../../guide/en/concept/di-container.md
337
+
#: ../src/guide/concept/di-container.md
330
338
msgid"This is primarily done in constructor and handing method of action handlers:"
331
339
msgstr""
332
340
333
341
#. type: Fenced code block (php)
334
-
#: ../../guide/en/concept/di-container.md
342
+
#: ../src/guide/concept/di-container.md
335
343
#, no-wrap
336
344
msgid""
337
345
"use \\Yiisoft\\Cache\\CacheInterface;\n"
@@ -359,17 +367,17 @@ msgid ""
359
367
msgstr""
360
368
361
369
#. type: Plain text
362
-
#: ../../guide/en/concept/di-container.md
370
+
#: ../src/guide/concept/di-container.md
363
371
msgid"Since it's [yiisoft/injector](https://github.com/yiisoft/injector) that instantiates and calls action handler, it checks the constructor and method argument types, gets dependencies of these types from a container and passes them as arguments. That's usually called auto-wiring. It happens for sub-dependencies as well, that's if you don't give dependency explicitly, the container would check if it has such a dependency first. It's enough to declare a dependency you need, and it would be got from a container automatically."
364
372
msgstr""
365
373
366
374
#. type: Title ##
367
-
#: ../../guide/en/concept/di-container.md
375
+
#: ../src/guide/concept/di-container.md
368
376
#, no-wrap
369
377
msgid"References <span id=\"references\"></span>"
370
378
msgstr""
371
379
372
380
#. type: Bullet: '- '
373
-
#: ../../guide/en/concept/di-container.md
381
+
#: ../src/guide/concept/di-container.md
374
382
msgid"[Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler](https://martinfowler.com/articles/injection.html)"
0 commit comments