@@ -68,23 +68,6 @@ final readonly class CachedWidget
6868We've avoided unnecessary inheritance and used interface to reduce coupling. You can replace cache
6969implementation without changing ` CachedWidget ` so it's becoming more stable.
7070
71- ### Why use private properties <span id =" why-private-properties " ></span >
72-
73- In the composition example above, note that the ` $cache ` property is declared as ` private ` . This design choice
74- supports composition by providing several benefits:
75-
76- - ** Encapsulation** : Private properties with getters/setters allow you to control access and make future changes
77- without breaking existing code.
78- - ** Data integrity** : Setters can validate, normalize, or format values before storing them, ensuring properties
79- contain valid data.
80- - ** Immutability** : Private properties enable immutable object patterns where setters return new instances rather
81- than modifying the current one.
82- - ** Flexibility** : You can easily create read-only or write-only properties, or add additional logic to property
83- access later.
84-
85- This approach embraces composition by ensuring objects have well-defined interfaces for interaction rather than
86- direct property access, making the code more maintainable and less prone to certain types of mistakes.
87-
8871The ` CacheInterface ` here is a dependency: an object another object depends on.
8972The process of putting an instance of dependency into an object (` CachedWidget ` ) is called dependency injection.
9073There are many ways to perform it:
@@ -93,21 +76,38 @@ There are many ways to perform it:
9376- Method injection. Best for optional dependencies.
9477- Property injection. Better to be avoided in PHP except maybe data transfer objects.
9578
79+ ### Why use private properties <span id =" why-private-properties " ></span >
80+
81+ In the composition example above, note that the ` $cache ` property is declared as ` private ` .
82+
83+ This approach embraces composition by ensuring objects have well-defined interfaces for interaction rather than
84+ direct property access, making the code more maintainable and less prone to certain types of mistakes.
85+
86+ This design choice provides several benefits:
87+
88+ - ** Encapsulation** : Private properties with getters/setters allow you to control access and make future changes
89+ without breaking existing code.
90+ - ** Data integrity** : Setters can validate, normalize, or format values before storing them, ensuring properties
91+ contain valid data.
92+ - ** Immutability** : Private properties enable immutable object patterns where setter ` with*() ` methods return
93+ new instances rather than modifying the current one.
94+ - ** Flexibility** : You can create read-only or write-only properties or add additional logic to property access later.
95+
9696
9797## DI container <span id =" di-container " ></span >
9898
99- Injecting basic dependencies is simple and easy . You're choosing a place where you don't care about dependencies,
99+ Injecting basic dependencies is straightforward . You're choosing a place where you don't care about dependencies,
100100which is usually an action handler, which you aren't going to unit-test ever, create instances of dependencies needed
101101and pass these to dependent classes.
102102
103- It works well when there aren't many dependencies overall and when there are no nested dependencies. When there are
103+ It works well when there are few dependencies overall and when there are no nested dependencies. When there are
104104many and each dependency has dependencies itself, instantiating the whole hierarchy becomes a tedious process, which
105- requires lots of code and may lead to hard to debug mistakes.
105+ requires lots of code and may lead to hardly debuggable mistakes.
106106
107- Additionally, lots of dependencies, such as certain third party API wrapper , are the same for any class using it.
107+ Additionally, lots of dependencies, such as certain third- party API wrappers , are the same for any class using it.
108108So it makes sense to:
109109
110- - Define how to instantiate such API wrapper once .
110+ - Define how to instantiate such an API wrapper.
111111- Instantiate it when required and only once per request.
112112
113113That's what dependency containers are for.
@@ -187,9 +187,10 @@ return [
187187
188188### Injecting dependencies <span id =" injecting-dependencies " ></span >
189189
190- Directly referencing container in a class is a bad idea since the code becomes non-generic, coupled to container interface
191- and, what's worse, dependencies are becoming hidden. Because of that, Yii inverts the control by automatically injecting
192- objects from a container in some constructors and methods based on method argument types.
190+ Directly referencing a container in a class is a bad idea since the code becomes non-generic,
191+ coupled to the container interface and, what's worse, dependencies are becoming hidden.
192+ Because of that, Yii inverts the control by automatically injecting objects from a container in some constructors
193+ and methods based on method argument types.
193194
194195This is primarily done in constructor and handing method of action handlers:
195196
@@ -219,9 +220,9 @@ final readonly class MyController
219220```
220221
221222Since it's [ yiisoft/injector] ( https://github.com/yiisoft/injector ) that instantiates and calls action handler, it
222- checks the constructor and method argument types, get dependencies of these types from a container and pass them as
223+ checks the constructor and method argument types, gets dependencies of these types from a container and passes them as
223224arguments. That's usually called auto-wiring. It happens for sub-dependencies as well, that's if you don't give dependency
224- explicitly, container would check if it has such a dependency first.
225+ explicitly, the container would check if it has such a dependency first.
225226It's enough to declare a dependency you need, and it would be got from a container automatically.
226227
227228
0 commit comments