I've recently learned the merits of dependency injection but am wondering if I should be using it in my project since I don't even require a full blown mvc. Now that I'm using it I'm realizing the extra overhead in each page that I write. For example...
require_once '../../include/session.class.php';
require_once '../../include/db.class.php';
require_once '../../include/account.class.php';
$objSession = new Session();
$objDb = new Db();
$objAccount = new Account( $objSession, $objDb );
account.class.php
class Account {
...
public function __construct( Session $objSession, Db $objDb ) {
$this->session = $objSession;
$this->db = $objDb;
}
}
...the Account class will always need Db and Session and I'll only ever have one class of each. So my question is, should I be using DI in a situation like this or should I just use...
account.class.php
require_once '../../include/session.class.php';
require_once '../../include/db.class.php';
class Account {
...
public function __construct() {
$this->session = new Session();
$this->db = new Db();
}
}
...?
Dependency Injection has nothing to do with MVC. It is really good at making unit tests easier to write and ultimately I have found that it makes me really think about the resources that I'm using and whether or not that implementation should be using that resource.
I personally don't see the harm in creating the injected object, so you've got a couple lines where you have to create an object? It tells the user a lot more about what's going on. I'd rather have clarity as compared to magic.
Personally, I think most of the clutter in the code is coming from the require statements. I'd say an autoloader would solve some of that problem.
I really enjoyed this Google Clean Code Talk on DI. It helped me grasp the concept and its benefits a little better.
You've read about the merits of dependency injection. Why did you start using it?
Was it because of the ability to swap out those particular dependencies for testing or different environments? Was it to isolate and make explicit the order of a circular chain of dependencies?
Suppose, for example, that it was the desire to inject different classes for testing purposes (the merit of DI that made me use it). How do you handle that without DI?
Look at your Account class. You can either modify the constructor with an if check on some predicate testMode(), or you can modify the Db and Session constructors, or you could possibly change a configuration file. Whatever non DI solution you opt for, are you ok with that? What about other dependencies (emailer, logger, etc)? Do you have any interfaces to external systems that you should mock for testing?
Anyway, the answer could be that you are satisfied without the DI solution and that your app is small enough to manage without it. But it's important to ask yourself the question anyway.
Similarly, apply that same line of questioning to the other merits of DI that motivated you to start using it.
Incidentally, do you have one instance of Db in Account and another in each of your other classes? Could you have just one instance? DI helps with that. You can have singleton classes without actually coding them as singletons by always injecting the same instance.
Out of curiosity, why are you doing your own dependency injection instead of using a DI library? Half of the benefit of using DI is that it is cleanly abstracted away by other people's implementations. Only write the code you need to and let the libraries take care of doing the injection for you. This is similar to drrcknlsn's suggestion, but without writing the actual implementation of the DependencyInjectionContainer class:
$account = DependencyInjectionContainer::build('Account');
and screw the rest.
A good DI library should see the constructor for Account, realize it needs a Db and a Session, and march up the chain of constructors (in this case, it ends there since both have empty constructors). That translates to having the same amount of code as the non DI case (plus the arguments to the constructor, minus the calls to the constructors inside, but no extra crap at top), with whatever benefits brought you to DI in the first place.
Dependency injection containers were invented to solve this very problem. Consider:
$account = DependencyInjectionContainer::build('Account');
The DependencyInjectionContainer class would handle the injection:
public static function build($class) {
switch ($class) {
case 'Account':
$session = new Session();
$db = new Db();
return new Account($session, $db);
// ...
}
}
Related
I've recently learned about the advantages of using Dependency Injection (DI) in my PHP application. However, I'm still unsure how to create my container for the dependencies, or whether I should be using DI at all for the online forum that I'm building.
The following code is my version of the DI container I have made based on the example I learned from here .
class ioc {
var $db;
var $session;
var $user_id;
static function newUser(static::$db, static::$user_id) {
$user = new User($db, $user_id);
return $user;
}
static function newLogin(static::$db, static::$session) {
$login = new Login($db, $session);
return $login;
}
}
$user = ioc::newUser();
$login = ioc::newLogin();
I have a few questions:
1) Where should I instantiate my injected dependencies, such as $database, $session, etc? Would it be outside the container class, or inside the container's constructor.
2) What if I need to create a multiple instances of the User class inside other classes? I can't inject the previously instantiated $user object because that instance is already being used. However, creating the multiple User instances inside of another class would violate the rules of DI. For example:
class Users {
function __construct($db, $user_id) {
$this->db = $db;
$this->user_id = $user_id;
}
function create_friends_list() {
$st = $this->$db->prepare("SELECT user_id FROM friends WHERE user_id = $this->user_id");
$st->execute();
while($row = $st->fetch()) {
$friend = ioc::newUser($row['user_id']);
$friend->get_user_name();
$friend->get_profile_picture();
}
}
}
3) I'm wondering if I should even adopt DI, knowing that I have to rewrite all of my previous code. I've previously been relying on global variables that I instantiate in my initialize.php, which is included in all my files.
It seems to me that DI creates a lot of overhead and there are situations where it is unusable (as in my #2 example). The following site is from a developer who cites many good reasons not to use DI. Does his arguments have any merit? Or am I just using DI wrong?
check this link.
Where should I instantiate my injected dependencies, such as $database, $session, etc? Would it be outside the container class, or inside the container's constructor.
Ideally your database connection and session would be bootstrapped in. Proper DI requires an instance of a base object for which everything is registered into. So taking your IOC class as an example you need to make an instance of it ($ioc = new IOC();) then you need some kind of service provider class say
$ioc->register('database', new DatabaseServiceProvider($host, $user, $pass))
Now every time you want a connection to the database you just need to pass in $ioc->get('database'); a very rough example but I think you can see the idea is basically to store everything inside a registry and nothing is statically binded meaning you can create another instance of $ioc with totally different settings making it easy to create connections to say a different database for testing purposes.
What if I need to create a multiple instances of the User class inside other classes? I can't inject the previously instantiated $user object because that instance is already being used. However, creating the multiple User instances inside of another class would violate the rules of DI.
This is a common issue and there are multiple different solutions. Firstly your DI should show the difference between logged in user and just a user. You would probably want to register your logged in user but not just any user. make your user class just normal and use
$ioc->register('login-user', User::fetch($ioc->get('database'), $user_id));
so now $ioc->get('login-user') returns your logged in user. You can then use User->fetchAll($ioc->get('database')); to get all your users.
I'm wondering if I should even adopt DI, knowing that I have to rewrite all of my previous code. I've previously been relying on global variables that I instantiate in my initialize.php, which is included in all my files.
If you need to rewrite all your code to use DI you shouldn't probably do it. Maybe look into making a new project and work in some of your old code if you have the time. If your codebase is large I would recommend looking into breaking it down into smaller projects and using RESTFUL apis for getting and saving data. Good examples of writing APIs would be for putting your forum search into its own application /search/name?partial-name=bob would return all users with the word bob in it. you could build it up and make it better over time and use it in your main forum
I hope you understand my answers but if you need any more info let me know.
I was going to write this a comment, but it grew too long. I am not an expert so I will just give my point of view from what I've learned through few years practicing and here in SO. Feel free to use or question any part of my answer (or none).
1.- Outside. What does the container do? The answer should be a single thing. It shouldn't have to be responsible to initialize the classes, connect to the database, handle the session and other things. Each class does one thing only.
class ioc
{
public $db;
// Only pass here the things that the class REALLY needs
static public function set($var, $val)
{
return $this->$var = $val;
}
static function newDB($user, $pass)
{
return new PDO('mysql:host=localhost;dbname=test', $user, $pass);
}
static function newUser($user_id)
{
return new User($db, $user_id);
}
static function newLogin($session)
{
return new Login($this->db, $session);
}
}
if (ioc::set('db',ioc::newDB($user, $pass)))
{
$user = ioc::newUser($user_id);
$login = ioc::newLogin($session);
}
2.- You shouldn't do $friend = ioc::newUser($row['user_id']); inside your class. There you are assuming that there's a class called ioc with a method called newUser(), while each class should be able to act on it's own, not based on [possibly] other existing classes. This is called tight coupling. Basically, that's why you shouldn't use global variables either. Anything used within a class should be passed to it, not assumed in the global scope. Even if you know it's there and your code works, it makes the class not reusable for other projects and much harder to test. I will not extend myself (PUN?) but put a great video I discovered here in SO so you can dig more: The Clean Code Talks - Don't Look For Things.
I'm not sure about how the class User behaves, but this is how I'd do it (not necessary right):
// Allow me to change the name to Friends to avoid confusions
class Friends
{
function __construct($db)
{
$this->db = $db;
}
function create_friends_list($user_id)
{
if (!empty(id))
{
// Protect it from injection if your $user_id MIGHT come from a $_POST or whatever
$st = $this->$db->prepare("SELECT user_id FROM friends WHERE user_id = ?");
$st->execute(array($user_id));
$AllData = $st->fetchAll()
return $AllData;
}
else return null;
}
// Pass the $friend object
function get_friend_data($friend)
{
$FriendData = array ('Name' => $friend->get_user_name(), 'Picture' => $friend->get_profile_picture());
return $FriendData;
}
}
$User = ioc::newUser($user_id);
$Friends = new Friends($db);
$AllFriendsIDs = array();
if ($AllFriendsIDs = $Friends->create_friends_list($User->get('user_id')))
foreach ($AllFriendsIDs as $Friend)
{
// OPTION 1. Return the name, id and whatever in an array for the user object passed.
$FriendData = $Friends->get_friend_data(ioc::newUser($Friend['user_id']));
// Do anything you want with $FriendData
// OPTION 2. Ditch the get_friend_data and work with it here directly. You're already in a loop.
// Create the object (User) Friend.
$Friend = ioc::newUser($Friend['user_id']);
$Friend->get_user_name();
$Friend->get_profile_picture();
}
I didn't test it, so it has probably some small bugs.
3.- If you are learning while coding, you will have to rewrite MANY things. Try to do somethings right from the beginning so you don't need to rewrite everything, but only the classes/methods and adopting some conventions for all your code. For example, never echo from within the function/method, always return and echo from outside. I'd say that yes, it's worth it. It's bad that you have to loose 1 or 2 hours just rewriting something, but if it has to be done, do it.
PS, sorry, I changed your bracket style everywhere.
EDIT
Reading other answers, while you shouldn't connect to the database with your ioc object, it should be perfeclty fine create a new object with it. Edited above to see what I mean.
Instead of globals in your init.php define your objects like:
ioc::register('user', function() {
return new User();
});
And inisde your create_friends_list method use:
ioc::get('user')->newUser($user_id);
This is a really plain implementation. Check out:
http://net.tutsplus.com/tutorials/php/dependency-injection-huh/?search_index=2
or
http://net.tutsplus.com/tutorials/php/dependency-injection-in-php/?search_index=1
for more information.
The question you asked has one very important catch, which I asked about in a comment. Any time you examine the possibility of pausing forward progress in order to go back and accomplish a less than trivial re-factoring of existing classes, you have to really think about the payoff.
You replied:
It seems a bit complex (and very different) and more work than it's worth to implement at this point. I'm just trying to hack out something real quick and see if it gains traction.
Remember that you have the following things to do if you want to implement an DI with an IoC container properly:
Implement the IoC container and registry at bootstrap
Modify all existing classes that have dependencies to allow setter injection, while not depending on the IoC container itself
Re-writing / Re-structuring of your tests as needed
A note on the second bullet which reflects my own personal view and preference, developing with DI in mind can be hard and you want the full reward it can give. One of the biggest rewards is completely decoupled objects, you don't get the complete part of that if everything still depends on an IoC container.
That's a lot of work, especially if you haven't been considering the pattern until now. Sure, you'll have clear benefits, such as lots of re-usable and easily testable objects when you're done. But, as with all re-factoring, nothing new would be accomplished in the context of adding or finishing new functionality and features. Is difficulty testing or tight coupling getting in the way of that? That's something you'd have to weigh.
What I suggest you do instead is keep the pattern in mind as you write new code. Provide setter methods to inject dependencies, which can be utilized manually or through an IoC container. However, have your classes continue to create them just in time if none have been injected and avoid composition in a constructor.
At that point you'll have a collection of classes that lend much better to inversion of control, if that's a pattern you want to pursue in the future. If it works well for you and it's something you really want to incorporate into your design decisions, you can easily re-factor to remove the JIT logic later.
In conclusion, I'm afraid that the only thing you'll end up with if you try implementing it completely, and properly right now is a mess. You can change how you write classes now going forward, but I wouldn't go back and try to implement it across the board.
I'm moving from Globals and Singletons (=bad?) to Dependency Injections (=good?) in PHP and I'm very new to it.
I have read many related topics on Stack Overflow already but I still can't understand the main principles of DI.
Please tell me if I'm doing it right (it's just shortened pseudo-code):
// first connect to DB
$sql = new Sql();
// create logger (I'm writing logs to Database so I need to pass $sql to it)
$log = new Log($sql);
// restore logged in user, get info about user, unread messages...
// class "User" needs access to Database and Logs:
$user = new User($sql, $log);
// now we need to collect all the data of current section of my Website
// I'm using Model and Controller:
$model = new FrontPageModel($sql, $user, $log);
$pageController = new FrontPageController($model);
Though it may look OK at this step but what if I need to get access to more classes like Config, Session, etc.?
Should my code transform to this?
$model = new FrontPageModel($sql, $user, $log, $config, $session);
Isn't it too much already?
I know someone could advice to use a kind of big "Application" class and put Config, Session, Log, Db objects inside of this class but I feel that it isn't very good idea.
Next question - what if I need to get logged User's ID inside of my FrontPageController? I did not pass an instance of "User" to FrontPageController, but it was passed before (in chain) to FronPageModel.
class FrontPageController{
private $model;
function __construct($model){
$this->model = $model;
}
function getData(){
echo $this->model->user->id; // is it right way?
}
}
That "$this->model->user->id" seems like overkill to me.
It might not be the prettiest, but you're certainly not doing it "wrong". You're demonstrating classing constructor injection, but you could perhaps refactor to keep some of the disparate objects separated a bit more.
My suggestion would be to look at established PHP DI containers. See how they work, use them in a few apps, and (1) you'll have much more testable apps and (2) you'll be much more comfortable with DI in general.
Take a look at one or more of the following:
Pimple
Aura DI
Symfony DI
Like all the joyful stuff, it' depends.
I would put everything inside a factory class, or several factory classes for different sub systems.
class AppFactory {
protected $_sql;
public function getSql()
{
if (!empty($this->_sql))
return $this->_sql;
$this->_sql = new Sql();
}
}
Then initial it on application run. Configure if needed.
$factory = new AppFactory();
// set config
// $factory->internallyGenerateSingletons = true;
And now every other class can use it. And of course you have injection to put factory inside.
$model = new FrontPageModel($factory);
// or
// $model->useFactory($factory);
Regarding other question. Is this the right way.
...
$this->model->user->id
...
I would say it's ok but batter is to use methods like this:
...
$this->model->getUser()->id
..
So you can mock user class when doing unit testing. And it makes application more flexible.
It seems like you have got the idea of dependency injection right. You even question Symfonies idea of DI (in a comment), which shows more mature understanding.
A next step to solving the questions you have is to take a step away from leaking technical information from one layer into another. Eg your controllers don't care that they talk to a model. Your model doesn't care it talks to an sql or nosql database.
Another is about responsabilities. Does the user really need to do all of that? Is the user responsible for logging? It may be a correct choice, but it also seems that you ask it to do a lot of things. Does the user construct itself, update itself? etc
$this->model->user->id; // is it right way? Is not the right way. 1) This is very strong coupling. 2) do you need the id of the user? is the user only put in as dependency to get something from it? perhaps something like $this->user->showUserInfo($userInfoDisplay) can be used?
I'm building out a small project to try to teach myself as much of the fundamentals as possible, which for me means not using a prefabricated framework (As Jeff once put it, "Don't reinvent the wheel, unless you plan on learning more about wheels" [emphasis mine]) and following the principles of Test Driven Development.
In my quest, I recently ran into the concept of Dependency Injection, which appears essential to TDD. My problem is that I can't quite wrap my head around it. My understanding so far is that it more or less amounts to "have the caller pass the class/method any other classes it may need, rather than letting them create them themselves."
I have two example issues that I'm trying to resolve with DI. Am I on the right track with these refactorings?
Database Connection
I'm planning to just use a singleton to handle the database, as I'm currently not expecting to use multiple databases. Initially, my models were going to look something like this:
class Post {
private $id;
private $body;
public static function getPostById($id) {
$db = Database::getDB();
$db->query("SELECT...");
//etc.
return new Post($id, $body);
}
public function edit($newBody) {
$db = Database::getDB();
$db->query("UPDATE...");
//etc.
}
}
With DI, I think it would look more like this:
class Post {
private $db; // new member
private $id;
private $body;
public static function getPostById($id, $db) { // new parameter
$db->query("SELECT..."); // uses parameter
//etc.
return new Post($db, $id, $body);
}
public function edit($id, $newBody) {
$this->db->query("UPDATE..."); // uses member
//etc.
}
}
I can still use the singleton, with credentials specified in the application setup, but I just have to pass it from the controller (controllers being un-unit-testable anyway):
Post::getPostById(123, Database::getDB);
Models calling models
Take, for example, a post which has a view count. Since the logic to determine if a view is new isn't specific to the Post object, it was just going to be a static method on its own object. The Post object would then call it:
class Post {
//...
public function addView() {
if (PageView::registerView("post", $this->id) {
$db = Database::getDB();
$db->query("UPDATE..");
$this->viewCount++;
}
}
With DI, I think it looks more like this:
class Post {
private $db;
//...
public function addView($viewRegistry) {
if ($viewRegistry->registerView("post", $this->id, $this->db) {
$this->db->query("UPDATE..");
$this->viewCount++;
}
}
This changes the call from the controller to this:
$post->addView(new PageView());
Which means instantiating a new instance of a class that only has static methods, which smells bad to me (and I think is impossible in some languages, but doable here because PHP doesn't allow classes themselves to be static).
In this case we're only going one level deep, so having the controller instantiate everything seems workable (although the PageView class is getting its DB connection indirectly by way of the Post's member variable), but it seems like it could get unwieldy if you had to call a method that needed a class that needed the class that needed a class. I suppose that could just mean that's a code smell too though.
Am I on the right track with this, or have I completely misunderstood DI? Any criticisms and suggestions are greatly appreciated.
Yes. It looks like you have the right idea. You'll see that as you implement DI all your dependencies will float to the "top". Having everything at the top will make it easy to mock the necessary objects for testing.
Having a class that needs a class that needs a class is not a bad thing. What your describing there is your object graph. This is normal for DI. Lets take a House object as an example. It has a dependency on a Kitchen; the Kitchen has a dependency on a Sink; the Sink has a dependency on a Faucet and so on. The House's instantiation would look something like new House(new Kitchen(new Sink(new Faucet()))). This helps to enforce the Single Responsibility Principle. (As an aside you should do this instantiation work in something like a factory or builder to further enforce the Single Responsibility Principle.)
Misko Hevery has written extensively about DI. His blog is a great resource. He's also pointed out some of the common flaws (constructor does real work, digging into collaborators, brittle global state and singletons, and class does too much) with warning signs to spot them and ways to fix them. It's worth checking out sometime.
Dependency injection is about injecting. You need some solution to inject the external object.
The traditional approaches are:
constructor injection __construnctor($dependecy) {$this->_object = $dependency}
setter injection setObject($dependency) {$this->_object = $dependency}
gettter injection getObject() {return $this->_dependency} and oveloading this method eg. from stub or mock in the tests.
You may also mix all the above, depends what you need.
Avoid static calls. My personal rule is use static only when you call some functions, e.g. My::strpos() or when dealing with singletons or registry (which should be limited to minimum, because global state is evil).
You will rarely need static methods when your app has a good dependency container.
Take a look at the other dependency injection + [php] topics on SO.
Edit after comment:
The container
Different frameworks handle the container in different way. Generally this is an object, which holds the instances of objects you need, so you don't have to instantiate new object each time. You may register any object with such a container, and then access it anytime you need.
The container may instantiate all the resources you need at boot time, or lazy load the resource when accessed (better solution).
As an example, consider:
Zend Application Resource Plugins
Symfony Dependency Injection Container
Another great reference:
http://martinfowler.com/articles/injection.html
It's certainly going into the right direction but you should not stop there.
The point of DI is to remove strong couplings between classes to allow for easier substitution of single components. This will allow for better testability because you can substitute dependencies more easily with Mocks and Stubs. And once your code is tested, it is much easiert to change and maintain.
Consequently, you should also remove those other aspects in your code that create strong coupling smells as well, e.g. remove the static methods and the singleton and any other globals.
For some more information on that, please see
How is testing the registry pattern or singleton hard in PHP?
http://gooh.posterous.com/singletons-in-php
http://kore-nordmann.de/blog/0103_static_considered_harmful.html
http://fabien.potencier.org/article/11/what-is-dependency-injection
EDIT: with a couple of others answers suggesting to use a DI container, I feel it's necessary to stress that you do not need a DI container to do DI. The second blog post in the last link given above discusses this.
To answer your questions: yes, you are on the right track. To give you more details: this is one of the best posts I found related to DI:
http://www.potstuck.com/2009/01/08/php-dependency-injection
You will understand what a container is:
$book = Container::makeBook();
Regarding the second example: in your method addView I would try to avoid passing the object $viewRegistry, I would check the condition outside in the controller.
I am building a really minimal MVC framework to increase my PHP knowledge and challenge myself. I've come to the point where Classes begin to be dependent on each other to work.
Dependency injection seems to be the solution to this and are used by some of the big frameworks around.
I've found Bucket on Github and have messed around it for a while to understand the basics. What I can't get my head around however is when it's appropriate to create a Container?
Making one big container including every possible class that may be needed seems nothing but counter-productive to me and I can't imagine that it is good practice. It seems like the recipe for bad performance at least.
In the alternative, which is to make multiple containers, I still don't get how the ever-stinking Singletons are not needed anymore.
Let's say that I would have the following code:
$session_container = new bucket_Container();
$session_container->create('Database');
$session_container->create('Database_Sessions');
$log_container = new bucket_Container();
$log_container->create('Database');
$log_container->create('Database_Log');
So here we have two containers, or in this case buckets for two totally different usages which are mutual by their dependency on the Database class.
My logic tells me that the above code will create two independent instances of the Database-class, meaning that I still would have to make the Database-class a singleton to ensure that concurrent instances of my database connection isn't occurring?
Is this correct?
I don't know much about the specific lib, but assuming it lets you use a factory, let the factory return the same instance.
Edit: Ok, this is simply on the Bucket GitHub index page.
class MyFactory {
function new_PDO($container) {
return new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
}
}
$bucket = new bucket_Container(new MyFactory());
$db = $bucket->get('pdo');
So in your case you could simply do:
class MyFactory {
private $pdo;
function new_Database($container) {
if($this->pdo){
return $this->pdo;
}
return $this->pdo = new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
}
}
$factory = new MyFactory();
$session_container = new bucket_Container($factory);
$session_container->create('Database_Sessions');
$log_container = new bucket_Container($factory);
$log_container->create('Database_Log');
Something like that. Doesn't seem like rocket science.
Edit2: I don't have enough rep points to comment on the question (bit silly), but in response to your "modularity" concern: think of the container as the "glue" of your application. Indeed, if you have a large application, you may want to "glue" inside an isolated part of your application only. That is a valid encapsulation concern. But even then you still need a container that handles injection at the highest level of abstraction. If you just create a separate container for every part of your application, you either end up with unneeded duplication of instances, or you have to apply another level of instance management, which doesn't improve the encapsulation in any way: you're still sharing instances between different parts of your application.
My advice would be to use a single container at the bootstrap level. If you want added encapsulation for specific parts of your application (modules, plugins, whatever), use "child containers". A child container inherits the instances from the parent container, but the parent container knows nothing of the child (as far as he's concerned, he's still a bachelor ;)). Could be that Bucket supports this by default, I know other DI containers do. If not, it's really easy to implement using a Decorator. Imagine something like this:
class MyContainerType extends bucket_Container {
private $_parent;
private $_subject;
public function __construct($factory = null, bucket_Container $parent = null){
$this->_parent = $parent;
$this->_subject = new bucket_Container($factory);
}
public function get($key){
$value = $this->_subject->get($key);
if($value){
return $value;
}
return $this->_parent->get($key);
}
/**
* Override and delegation of all other methods
*/
}
Making one big container including every possible class that may be needed seems nothing but counter-productive to me and I can't imagine that it is good practice. It seems like the recipe for bad performance at least.
On the contrary. This is exactly what you would do with a di container. The container will only instantiate objects on demand, so there is virtually no overhead to managing all you singleton-ish classes through it.
The biggest problem with di is to distinguish between shared objects (Things you would usually think of as singletons) and transient objects (Objects that have plenty of instances through a normal application flow.). The former are easily managed through di. The latter don't really fit. Having those two "kinds" of objects clearly distinguished may seem like a bit of a hassle, but is really a highly beneficial side effect of using a di container.
If you are worried about multiple simultaneous connections you can just use mysql_pconnect() or the equivelant for the database you are using. It will check if a connection is already open and use the existing connection if it is.
As far as the container issue, I've seen it done in two ways, which you seem to be aware of both. The first method is to have the framework read your database schema and create classes fore each table. I personally don't like this approach. Symfony is one framework that does this (by using the doctrine ORM).
The more preferred method I've seen is to have a generic container, which basically builds the sql for you given a table, columns and an action. This is the approach taken by codeIgniter:
$query = $this->db->get('mytable');
$query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);
I hear people talking about dependency injection and the benefit of it all the time, but I don't really understand it.
I'm wondering if it's a solution to the "I pass database connections as arguments all the time" problem.
I tried reading wikipedia's entry on it, but the example is written in Java so I don't solidly understand the difference it is trying to make clear. ( http://en.wikipedia.org/wiki/Dependency_injection ).
I read this dependency-injection-in-php article ( http://www.potstuck.com/2009/01/08/php-dependency-injection/ ), and it seems like the objective is to not pass dependencies to an object directly, but to cordon off the creation of an object along with the creation of it's dependencies. I'm not sure how to apply that in a using php functions context, though.
Additionally, is the following Dependency Injection, and should I bother trying to do dependency injection in a functional context?
Version 1: (the kind of code that I create, but don't like, every day)
function get_data_from_database($database_connection){
$data = $database_connection->query('blah');
return $data;
}
Version 2: (don't have to pass a database connection, but perhaps not dependency injection?)
function get_database_connection(){
static $db_connection;
if($db_connection){
return $db_connection;
} else {
// create db_connection
...
}
}
function get_data_from_database(){
$conn = get_database_connection();
$data = $conn->query('blah');
return $data;
}
$data = get_data_from_database();
Version 3: (the creation of the "object"/data is separate, and the database code is still, so perhaps this would count as dependency injection?)
function factory_of_data_set(){
static $db_connection;
$data_set = null;
$db_connection = get_database_connection();
$data_set = $db_connection->query('blah');
return $data_set;
}
$data = factory_of_data_set();
Anyone have a good resource or just insight that makes the method and benefit -crystal- clear?
Dependency injection is a big word for "I have some more parameters in my constructor".
It's what you did before the awfull Singleton wave when you did not like globals :
<?php
class User {
private $_db;
function __construct($db) {
$this->_db = $db;
}
}
$db = new Db();
$user = new User($db);
Now, the trick is to use a single class to manage your dependencies, something like that :
class DependencyContainer
{
private _instances = array();
private _params = array();
public function __construct($params)
{
$this->_params = $params;
}
public function getDb()
{
if (empty($this->_instances['db'])
|| !is_a($this->_instances['db'], 'PDO')
) {
$this->_instances['db'] = new PDO(
$this->_params['dsn'],
$this->_params['dbUser'],
$this->_params['dbPwd']
);
}
return $this->_instances['db'];
}
}
class User
{
private $_db;
public function __construct(DependencyContainer $di)
{
$this->_db = $di->getDb();
}
}
$dependencies = new DependencyContainer($someParams);
$user = new User($dependencies);
You must think you just another class and more complexity. But, your user class may need something to log messages like lot of other classes. Just add a getMessageHandler function to your dependency container, and some $this->_messages = $di->getMessageHandler() to your user class. Nothing to change in the rest of your code.
You'll get lot of infos on symfony's doc
Your first example IS dependancy injection, you are injecting the dependency on the database object into the function.
Sarah has said this isn't, but imo it is, I believe she is thinking of dependency injection containers which are the next level up:
http://components.symfony-project.org/dependency-injection/trunk/book/02-Dependency-Injection-Containers
None of your examples look like dependency injection, version one is the closest though. Dependency injection is a technique used in object oriented programming, where the constructor of an object has arguments for the service objects it needs, and those service objects are passed in by the creator of the instance (which could be a factory, a test, or a dependency injection framework).
To get around your 'always passing the connection object' problem you may want to consider the template pattern. The template pattern is basically an abstract base class with the common part of a repeated code block, and abstract methods to allow for the variation between the instances of those repeated code blocks. Basically the base is a template of a block of code, and the abstract methods are the blanks to be filled in. I personally use the template method pattern to do my database resource control in Java.
I have done much searching on this topic myself (PHP Dependency Injection) and haven't found much to my liking. A lot has been written on the subject for other languages (Google Guice - http://code.google.com/p/google-guice/ ; Java Spring), but I couldn't find much available for PHP. Regardless of the language, however, the challenges are similar.
The three versions you list in your question are the typical approach. Version 3 is the closest to the direction in which I have seen the industry going. By shifting the responsibility of creating your dependent objects outside of your class, you are free to manipulate them as you please in your test code. However, the problem that I encountered with that approach is that you end up with long chains of dependent objects in your constructor that can potentially not even be used by the receiving object, but get passed through to an secondary dependent object. It gets messy and you lose knowledge of what is coming from where.
The Dependency Container example by #Arkh and #mmmshuddup is a great start, but I nonetheless found limitations with that approach as well. The final solution upon which I arrived was a custom built solution modeled somewhat after the Cake Pattern popular in Scala. It allows you to pass a single dependency into each of your constructors AND it lets you define the default construction of the dependent objects per class. This frees you from long dependency chains as well as losing control of the default implementations of your dependencies.
I called the system Diesel and I've been really happy with it. I published the code on github for anyone interested. You can get to it from the blog I wrote on the subject, which describes the basic usage as well as goes into more detail on your question. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/
Dependency Injection is the idea of removing the dependency between 2 components in order to focus on why they are dependent.
Imagine you have a component A that needs to use the services of another component B.
If you hardcode the existence of B inside A, then you will be stuck when you will want A to use the sames services, but implemented by another component.
So usually, you define a service interface that B and C will implement, and you make sure that when you use A, you feed it with objects compatible with the needed interface.
In your case, you might consider that your interface is a service on which you can make a query.
Your first case is the one that is the closer to the idea of Dependency Injection.