Disclaimer: I'm just learning DI myself. Take it with salt.
Including dependencies is just dependency injection. If your object-oriented design makes the Family object responsible for creating Member instances, then be sure to create the Family object, since in this case the Member will no longer be considered a Family dependency, but it is responsible. Therefore:
class Family { /** * Constructor. * * Since you have decided in your OO design phase that this * object should have the responsibility of creating members, * Member is no longer a dependency. MySQLi is, since you need * it to get the information to create the member. Inject it. * */ public function __construct($id, MySQLi $mysqli) { $this->id = $id; $this->mysqli = $mysqli; } /** * Query the database for members data, instantiates them and * return them. * */ public function getMembers() { // Do work using MySQLi } }
But if you think about it, should Family really be responsible for creating a Member ? It is better to have another object, for example FamilyMapper to create a Family with its members. Like this:
class FamilyMapper { /** * Constructor. * * A better OO design, imho is using the DataMapper pattern. * The mapper responsibility is instantiating Family, * which means it going to have to connect to the database, * which makes MySQLi its dependency. So we inject it. * */ public function __construct(MySQLi $mysqli) { $this->mysqli = $mysqli; } public function findByID($familyID) { // Query database for family and members data // Instantiate and return them } } class Family { /** * Constructor. * * Family is an object representing a Family and its members, * along with methods that *operate* on the data, so Member * in this OO design is a dependency. Inject it. * */ public function __construct($id, MemberCollection $members) { $this->id; $this->members; } public function getMembers() { return $this->members; } }
Using this template, your domain objects along with their methods (which may contain business logic) will be separated from your data access code. This is a good thing about dependency injection - it makes you rethink your OO design so you get cleaner code.
Many people think that using dependency injection means using non-factories and so on. This is not true! Including dependencies is just injecting dependencies. You can also use dependency injection with factory objects by introducing factory dependencies instead of the factory creating its own dependency.
Useful links:
Additions
Take the salt material here again.
Also note that there is a difference between dependency injection container and dependencies. The first of these is a simple concept of injection dependencies instead of creating the objects themselves (which leads to a very high connection). We see this from the above example.
The last term for frameworks / libraries that deal with dependency injection, so you do not need to do manual injection. The responsibility of the container is depending on the wiring, so you do not need to do the dirty work. The idea is that you define a dependency injection configuration that tells the container which dependency objects are Foo and how to enter them. The container reads the documentation and injects for you. This is what DIC libraries do, such as Pimple, SimpleDIC.
You can compare dependency injection containers with factories, since both are creation objects whose only task is to create objects. Although factories often specialize (i.e. FamilyMemberFactory creates instances of MemberInterface ), the dependency injection container is more general. Some people say that using the dependency injection container eliminates the need for factories, but you should remember that this means that you need to create and maintain dependency attachment configuration files, which can be thousands of XML / PHP lines.
Hope this helps.