PHP injection dependency when constructor arguments are not available

We are just starting to make a concerted effort to evenly use dependency injection in our project, and I ran into a problem.

I am writing a class to handle MongoDB requests. I pass MongoClient as a constructor dependency, no problem. But how do I handle the dependency when the variable needed to instantiate the object is not available during instance creation?

In particular, we have a wrapper for the MongoCollection findOne method, which, if you pass a string, is currently (in the old code) turning that string into MongoId with the "new MongoId ($ _ id)" and uses this for the search function.

From what I learned about dependency injection, having a “new MongoId” is a bad idea, and I already know that it will be difficult to write test cases for a function that converts a string to MongoId.

But how do I handle the injection when the MongoId class accepts the id string in the constructor?

The only thing I thought about this is to go on to close the constructor of the class, which does something like:

$getMongoId = function( $id ){ return new MongoId( $id ); }; 

from

 class MyMongo { function __construct( MongoClient $client, Closure $mongoIdGetter){...} } 

[edited to fix this last part]

But is this the right way to handle this? Of course, if we use DiC, we can do this, but the closure requirement for the constructor seems a bit. Am I just too dogmatic about injecting my addictions? I could fix this easily using the "new MongoId ($ _ id)" in the new class. I guess.

+8
php dependency-injection mongodb
source share
2 answers

Instead of closing you can use Factory:

 class MongoFactory { public function createMongoDb($id) { return new MongoId($id); } } 

Factories believe that there is a "new something" hard-coded dependency, because creating objects is their only goal, and you can easily replace them with another Factory.

Now your consumer class ( MyMongo ) will have a dependency on MongoFactory (or its interface if you do), which you can easily "enter".

+2
source share

But how do I handle the dependency when the variable needed to instantiate the object is not available during instance creation?

PHP will be a fatal error before you have the opportunity to deal with it yourself. If you use type parameters and / or do not define them by default, null PHP will be a fatal error when this parameter is not passed to any function.

From what I learned about dependency injection, having a “new MongoId” is a bad idea, and I already know that it will be difficult to write test cases for a function that converts a string to MongoId.

Will it be (in PHPUnit)?

 $this->assertInstanceOf('\MongoId', $getMongoId($id_string)); 

But how do I handle the injection when the MongoId class accepts the id string in the constructor?

I don't know what you mean by this, but you should test the result of MongoId processing.

The last bit of your question is losing me a bit, I think this is because it is not true, PHP (i.e. $__construct ).

I'm not sure why you need to embed a function in a class. I mean what I have the most:

 function findById($id){ if(!$id instanceof \MongoId) $id = new MongoId($id); return $this->getCollection()->findOne($id); } 

You do not need anything else, and you do not need to test the MongoId constructor, since it has already been tested by the module, you should instead test your public API, and not some other one.

+1
source share

All Articles