Jump to content

Static Methods vs. Singleton vs. Dependency/constructor Injection


adam_bray

Recommended Posts

I'm looking for some clarification here from different viewpoints to understand real world applications.

In a previous thread, I suggested to someone that they read up on singleton methods to restrict class duplication (oops!), I was quickly (and rightfully) shot down. I did this after having read through blog posts that also suggested singleton design to stop multiple MySQL connections. At the time I didn't consider that could be useful to some people.. fair enough.

Thankfully I don't use singleton methods within my own code, but I do use static methods for most things. Reading through numerous blog posts, tutorials, etc.., it seems like static methods can also be considered anti-design and is something to avoid.

So now it seems I'm at a point where I need to rewrite my existing framework & CMS, probably using dependency injection within my classes. I understand how this works, and why it makes sense.

What I'm struggling with is understanding how to use dependency injection within a (personal) CMS application.

For example - 

  • I have a config.ini file
  • I have a class that reads the .ini file, stores the variables, and provides me methods to access them
  • I have a content class that selects the relevant page/component from the DB (db & config dependency), then displays it via my template engine.
  • Within the included view files I call component classes (articles, contact, etc..), each of these require a connection to the DB, which has a config dependency.

Here's some code to explain it better -
index.php

<?php
$settings = '/config/config.ini';

$config = new Config($settings);

$db = new Database($config);

$content = new Content( $db ); // Config may also be passed for content config - keeping it simple for example
print $content->loadPage($_GET['page']); // This would now include the code below
?>

Let's say that this then loads the article index (through $content->loadPage()). The view would look something like this -
article_index.php

<?php
// Duplicated code
$settings = '/config/config.ini';

$config = new Config($settings);

$db = new Database($config);

// Article code
$articles = new Articles_Model($db);
return $articles->getArticles(0,15);
?>

Now my problem is that I'm duplicating the config and db class calls for no reason.

Is the sollution to store these within a registry class? But then I'm creating globals, which again seems anti-design.

Or is the problem how I load the active page?

Any insights would be much appreciated.

"Anti-design" does not mean something is bad. It means it's easy to abuse the design towards a bad end. Registries, singletons, static members, being anti-design means that you should think about how you are using them, not that you have to avoid them entirely.

 

I could go for any of:

a) A registry of the values, as you do need to propagate values across multiple locations

b) A singleton for the various objects, but only if there are never multiple configuration files, configuration objects, or database connections

c) Dependency injection by way of variables: have loadPage() set values, maybe looking like

print $content->loadPage($_GET['page'], array('db' => $db));
and then you'll have $db (or $this->db or whatever) set for you. This actually shares a lot in common with (a).

None of your examples includes a DI. Here's a rewrite of your index.php with DI:

 

$di = include 'includes/di.php';

$di['content']->loadPage($_GET['page']);
And your article_index.php

 

$di = include 'includes/di.php';

$di['articles']->getArticles(0, 15);
The includes/di.php could look something like:

 

// download from http://pimple.sensiolabs.org/
$container = new Pimple();

$container['config_filepath'] = 'config/config.ini';

$container['config'] = function($c) {
    return new Config($c['config_filepath']);
};

$container['db'] = function($c) {
  return new Database($c['config']);
};

$container['content'] = function($c) {
  return new Content($c['db']);
};

$container['articles'] = function($c) {
  return new Articles_Model($c['db']);
};

return $container;
For all your autoloading you may want to consider composer

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.