Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm using a simple project to help me understand and implement MVC with DI in preparation for unit testing. The site simply will display a different table of data based on the page requested. The difficulty comes in the data could come from different data sources (mysql or oracle for example), so I'm trying to implement DI to reduce the code needed to switch between the two. My problems are these:

1) Where to instantiate the data source (could be mysql, oracle or even a plain old array) and get it to the object(s) that require it (is DI even the best pattern for this)?

2) Where in the structure of things to put the data query specific to its source? Per my example below, I have a class Foo that queries a MySQL database for data but if I move to an Oracle database later it all has to be rewritten for a different syntax. Do I just create two versions FooMysql and FooOracle and tell something somewhere which to use?

Here is some basic, incomplete code demonstrating the concept as I'm seeing it. Hopefully you understand where I'm going with this and can point me in the right direction. I am not looking for an already built framework.

$c = new Controller('foo');
print_r($c->getContent());

class Controller
{
    private $view = null;

    public function __construct($viewName)
    {
        $this->view = new $viewName($dbc); // where to get and pass dbc based on view
    }
}

interface ViewInterface
{
    public function getContent();
}

class FooView
{
    private $foo = null;

    public function __construct(DatabaseConnection &$dbc)
    {
        $this->foo = new Foo($dbc);
    }

    public function getContent()
    {
        return $this->foo->getAll();
    }
}

class BarView
{
    private $bar = null;

    public function __construct(DatabaseConnection &$dbc)
    {
        $this->bar = new Bar($dbc);
    }

    public function getContent()
    {
        return $this->bar->getAll();
    }
}

interface StorageInterface
{
    public function getAll();
}

class Foo implements StorageInterface
{
    private $dbc = null;

    public function __construct(DatabaseConnection &$dbc)
    {
        $this->dbc = $dbc;
    }

    public function getAll()
    {
        // mysql code to get all foos
    }
}

class Bar implements StorageInterface
{
    private $dbc = null;

    public function __construct(DatabaseConnection &$dbc)
    {
        $this->dbc = $dbc;
    }

    public function getAll()
    {
        // oracle code to get all bars
    }
}
share|improve this question

1 Answer

1) Where to instantiate the data source (could be mysql, oracle or even a plain old array) and get it to the object(s) that require it (is DI even the best pattern for this)?

With DI you will have a separate DI container that handles creating instances of dependencies needed for your controllers. DI is an excellent choice because it will eliminate the need to have flow/control statements (if/else, switch/case) that have to figure out what DB your connecting to and lends itself to easy unit testing. With DI you tell the object this is what you will connect to.

2) Where in the structure of things to put the data query specific to its source? Per my example below, I have a class Foo that queries a MySQL database for data but if I move to an Oracle database later it all has to be rewritten for a different syntax. Do I just create two versions FooMysql and FooOracle and tell something somewhere which to use?

No, you will create an interface for you database classes. That way when you pass the dependency to your controller it will be agnostic to what type the database is.

Ex.

public interface IDatabase {
    function connect();
    function query();
}

public class MySQLDB implements IDatabase {
    function connect() {
        // specific connection properties for mysql
    }
    function query() {
    }

}

public class PostgresDB implements IDatabase {
    function connect() {
        // specific connection properties for postgres
    }
    function query() {
    }
}

public class FooController {
    private $dataBase = null;

    public FooController(IDatabase $dataBase) {
        // guard clause
        if ($database == null)
            throw new Exception("IDatabase");

        $this->dataBase = $dataBase;
    }

    public index() {
        $this->dataBase->query();
    }
}

public class BarController {
    private $dataBase = null;

    public FooController(IDatabase $dataBase) {
        // guard clause
        if ($database == null)
            throw new Exception("IDatabase");

        $this->dataBase = $dataBase;
    }

    public index() {
        $this->dataBase->query();
    }
}

// will be hooked into your http request lifecycle
// to figure out what controller and even method is being called
// this will then return your composed controller
// we are newing up dependencies here, but they are all isolated in one location
// this way the rate of change among classes are not affecting each other
public class DIContainer {
    public resovleController() {
        // find out the http request info
        if (FooController) {
            return new FooController(new MySQLDB());
        } elseif (BarController) {
            return new FooController(new PostgresDB());
        }
    }
}

Also there are some code smells in your example, try getting rid of the newing of classes.
Also the views shouldn't be responsible for handling what dependency to pass.
You will definitely need to learn about creating a DI container, and organizing your code in namespaces.
You will also need to create a front controller where your DI container will be able to load into or the DI container can be your front controller

Hope this helps.

share|improve this answer
1) DIC is where I was leaning towards so I guess I will continue in that direction 2) I'm already interfacing the database methods, i'm more interested in how to handle different query syntaxes. See updated question. – fwrawx 38 mins ago
Ignore my comment for #2, that was the answer (which I am already doing). As far as the code smell, I have inherited my MVC knowledge from existing code which I've always felt was stinky but haven't found a good complete example that implements good DI. Any insight? – fwrawx 5 mins ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.