Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I asked this question at stackoverflow and received no response (closed as duplicate with no answer). I'm experimenting with OOP and I have the following basic MVC layout:

class Model {
    // do database stuff
}

class View {
    public function load($filename, $data = array()) {
        if(!empty($data)) {
            extract($data);
        }

        require_once('views/header.php');
        require_once("views/$filename");
        require_once('views/footer.php');
    }
}

class Controller {
    public $model;
    public $view;

    function __construct() {
        $this->model = new Model();
        $this->view = new View();

        // determine what page we're on
        $page = isset($_GET['view']) ? $_GET['view'] : 'home';
        $this->display($page);
    }

    public function display($page) {
        switch($page) {
            case 'home':
                $this->view->load('home.php');
            break;
        }
    }
}

These classes are brought together in my setup file:

// start session
session_start();

require_once('Model.php');
require_once('View.php');
require_once('Controller.php');

new Controller();

Now where do I place my database connection code and how do I pass the connection onto the model?

try {
    $db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_DATABASE.'', DB_USERNAME, DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $err) {
    die($err->getMessage());
}

I've read about Dependency Injection, factories and miscellaneous other design patterns talking about keeping SQL out of the model, but it's all over my head using abstract examples. Can someone please just show me a straight-forward practical example?

share|improve this question
    
Fetching the appropriate data ("model") is the responsibility of the controller (application layer). It's perfectly fine to inject the data access into a controller or instantiate it directly in there. If data access logic is complicated, encapsulate it in its own class (data retrieval service for a specific functionality, also called repository pattern. This is part of the application layer as well); 'nuf said; –  Falcon Dec 9 '12 at 15:26
    
Connection strings in MVC frameworks are usually set in configuration files. The SQL bits of your code should retrieve the settings somehow, either through file access (and/or cache them in memory). –  Spoike Dec 9 '12 at 15:28
    
@Falcon are you saying the db connection should be in the Controller construct? And if so, would you mind showing me a simple example of how I could then execute a query in the Model? –  mister martin Dec 9 '12 at 15:37
    
@mister martin: No, I wouldn't say the db connection should be initialized there. It should be encapsulated in a class (repository) and possibly injected. Why would you want to have data access in the model (domain layer)? I consider data access to be used in the application or service layer exclusively. If you need to fetch related records then let that be done via lazy initialization by your ORM or design your aggregates the right way. In any case: Your model should be independent of the database connection! –  Falcon Dec 9 '12 at 15:42
    
@Falcon it is my understanding that the Model should handle all interaction with the file system or database, whereas the Controller simply acts like a browser (fetch data from Model and send to View) and the View displays the data. Is that wrong? I don't follow what you're saying. I get lost in all the terminology and am more of a visual learner; if you could show me some code that relates to my original post I would really appreciate it. –  mister martin Dec 9 '12 at 16:09

2 Answers 2

It all depends on how much design and abstraction you want to put in your code. Your code is fine if you want to keep things relatively simple, and have flexibility without to much headaches or code writing. Put your database access in a dedicated object, which will pull data of the DB and construct your Model object for you (it's a factory). Then, within the controller method query that factory to retrieve the correct model instance to populate your view. The model itself doesn't really need to know where it is coming from, so the factory is free to construct it from a file based storage instead. The only things that your factory will need is some parameters (say the $_GET relevant fields in your code), to figure out which data it must fetch.

class ModelFactory {
    private $dbhandle;
    function __construct(){
          // open db etc...
    }
   function loadModel($params){
         // run db queries and construct/fill up the Model instance
   }
   function saveModel($model){
        // pull out model fields to fill the insert/update query
   }
   // etc...you get the idea
}

Next, if you have a basic model layer where domain objects are direct transpositions of database rows, as it's mostly the case with direct use of the ActiveRecord pattern, and you only need to let the end user do CRUD operations, then just do that. Get inspiration from that pattern to build your ORM on top of it, and you get basic Master/Detail, one to many, many to many relationships handled for you. That would be a first step in the right direction (you can have look at early versions of cakephp or code igniter to get a feeling of how this works), but if you want to do it the right way(TM), then you will see that MVC can be much more complicated.

The MVC architecture is actually more abstract than that. The model part is a "layer" in the application, comprising a set of different services, in a very broad sense, which basically let you embody "higher level" functionalities (think authentication for instance, where you need to pull data from different places, but these details should not leak out to the controller level), which may be used in different requests, then domain objects (like a user), then data mappers (like the ActiveRecord pattern).

There are excellent posts on SO on that topic, like this one, covering that topic in details.

share|improve this answer

Like Falcon mentioned, the data access code should be in the Controller, at least the only access to a service layer or data access layer should be done from the Controller. The Model is mostly used to structure the data you want to show in the view, in other words it should mimic your domain model. Typically, you would query data from the database, create a Model with the data, load the Model onto the View, all within the your Controller (in general terms, implementation might differ).

In your example, it might look like this (again, just an overview example),

class Model {
    // domain model properties: id, name, age... 
}

class View {
    // view stuff        
}

class Repository {
    function __construct() {
       // connect to database and return a viable connection for data access
    }
}

class Controller {
    public $model;
    public $view;
    public $repository   

    function __construct() { 
        $this->repository = new Repository();       

        $this->model = new Model();
        $this->model = $this->repository.LoadModelFromDatabase();

        // load your model onto the view
        $this->view = new View($this->model);

        // determine what page we're on
        $page = isset($_GET['view']) ? $_GET['view'] : 'home';

        // display your view with your model loaded
        $this->display($page);
     }

     public function display($page) {
         switch($page) {
             case 'home':
                 $this->view->load('home.php');
             break;
     }
}

You should follow a similar pattern for other Views and Models, using your Controller to coordinate access to the database and interaction with your program.

share|improve this answer

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.