I am migrating a legacy code base to something more testable. To level set, we have about a dozen classes that are fairly close to being testable (I think?), but we have around 140 functions that have not yet been migrated to become classes.

One of the issues we have run into is that the majority of the code passes around the $db object, which is in the global scope (yuck!).

I've read with interest here that this sort of thing is best resolved with Dependency injection. I've started down that path, and have manual DI for most, with the $db object being a parameter for the calls.

Now I want to go the next step, and get those files testable. I understand that the way to do that should be to use the DI container. My project has composer, so I am leaning towards Pimple, which is a really simple DI container.

But before I start hacking on that, are my assumptions/understandings correct? Is using a DI container going to make it easier to test my units of code? With the DI container, can I also move other objects (like configuration values) into the container, so we just need to pass the container into the units of code, and get both DB & configs?

I don't think a DI container will make you testing easier. A DI container helps by allowing you to predefine prerequisites to simplify creating object that inject or need dependencies injected. I think what you are looking for is Mocks. You can Mock your DB object and inject it giving you control without needing a database during testing.

PS - Congratulations on transitioning to classes and DI! And don't worry about common objects in the global scope (assuming register_globals is off as is normal).

Hmm! Interesting. I was having trouble understanding how I was going to test relatively simple classes that relied on $db being there. After your post, I read up on Mocking a DB, and it seems it would work for most of the simple cases. But then I stumbled onto the dbUnit element, and *woah*, I can build an entire fake database for testing?! Awesome.

Christopher wrote:

A DI container helps by allowing you to predefine prerequisites to simplify creating object that inject or need dependencies injected. I think what you are looking for is Mocks. You can Mock your DB object and inject it giving you control without needing a database during testing.

Well, to be honest, I didn't really know what I was looking for. I had some simple classes, and wanted to test them, but couldn't see past how to satisfy the $db need.

Christopher wrote:

PS - Congratulations on transitioning to classes and DI! And don't worry about common objects in the global scope (assuming register_globals is off as is normal).

Well, see, that assumption is entirely reasonable. Unfortunately, its NOT the case in the code base I am working on! Ack! We have a horrible bit of code that takes the post/get super globals and sticks them in the global scope. Its a mess, and that needs to go. But in the meantime, I want to do the right thing where I can. For the new code, I'm trying to make it clean and testable, and where possible, to eliminate globals.

So one of my questions remains. Can I use a DI container to store both config variables and a database object? Or is that worse than just having a $config and $db object?

We have a horrible bit of code that takes the post/get super globals and sticks them in the global scope. Its a mess, and that needs to go. But in the meantime, I want to do the right thing where I can. For the new code, I'm trying to make it clean and testable, and where possible, to eliminate globals.

I would recommend wrapping the HTTP vars in a Request object that is a container for those value, plus support for dealing with post, get, ajax requests.

The Phoenix wrote:

So one of my questions remains. Can I use a DI container to store both config variables and a database object? Or is that worse than just having a $config and $db object?

Typically you would use some kind of Container object to hold the config variables. And a Registry to hold the $config and $db (and other) objects. It up to you whether you put the $config object and the $db object in a Registry and inject that, or inject the DI object and use it to instantiate objects where needed. Or a mix. DI objects are often used to instantiate objects that have complex wiring -- unlike the $config and $db objects to which you usually just pass an array or a few params.

Who is online

Users browsing this forum: No registered users and 3 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum