Stupidly Easy MVC in PHP or "We don't need no stinkin' framework!"

One day I sat, faced with this huge 'god' class that managed view, edit, add, delete for two components in one page. There was no value to having all that in a class, other than having a nice neat little "package." I considered breaking it into two classes, one for each component (which was really in the end one) but keeping the same basic methods … ehh, that didn't sit too well with me. I wanted to use templates, make it super easy to update when the powers that be changed their mind or wanted to add something. Then ... after a day of staring it and it and making some notes -- a light bulb went off in my little head. I fired up my laptop, opened some ruby files I had made. Looked at a "controller" file... ok... then looked at a "model" file... ok... then looked at a view file... Ah ha! Bingo.

Not wanting to start a whole new honking framework package (although for the first time I had a fleeting thought, HEY I can start a sourceforge project!!!) just for this one small app... I didn't want (and probably would have a hard time getting approved by sys admins) a framework like Solar, PHPOnTrax, CakePHP or Cerebral Cortex (whew! did I miss any?). But, this was so stupidly easy... and I just had one little application..

Don't get me wrong, I LOVE frameworks. I love to read and study them. But sometimes I can't just go start using a framework for one reason or another! or I am just doing a simple app and don't need a whole lot of frame :)

For those of you new to MVC it works like this in my understanding of webapps: The controller which is the brain, figures out what to do and calls the data model to retrieve the data and then it sends it to the view. That’s it. Wham-o. What I am doing is maybe more of a Page Controller. Perhaps some more knowledgeable person wants to comment on this?

For my Stupidly Easy MVC I had to do a big of ground work before I could make the classes for my little application. My little app is a page that displays a list of urls with descriptions, with add/edit buttons. Here's my task breakdown:

  • showEditForm (form contains url, description)
  • showAddForm (form contains url, description)
  • addLink (if no id is set, insert new. Othewise update record)
  • displayList (default action, displays the page title, description and all links)

I thought I'd have a variable, lets call it $action that would contain a string matching the name of one of the methods listed above. If you want to get really OOP savvy I think its called its called a message.

See Controller source code
The important part of this code:

 
    function doAction($method = "defaultMethod", $params = array() ) {
       // print "Action: $method";
        if (empty($method)) {
            $this->defaultMethod($params);
        } else if (method_exists($this, $method)) {
            call_user_func(array(&$this, $method), $params);
        } else {
            $this->nonexisting_method($method);
        }
    }

    function defaultMethod($params) {
        print "This is a default action. ";
    }

    function nonexisting_method($method) {
        print "Sorry, that method '$method' does not exist.";
    }

If there are any parameters, they would be in the $param array.

Wehn the controller receives the $action "method" it would call the method of that same name. However if it received nothing for $action it would call the method of the name "defaultMethod." If it received a method "gobblygook" it would call the method "nonexisting_method." You can display a more user friendly message, perhaps giving an admin email to contact if the user thought it was an error (or put it in a log).

See View source code
The View class is basically a wrapper for smarty. This way, if we later decide to do Savant or something, we can change this class to implement a different template. It has the usual template methods such as assign, display, fetch. Pretty simple.

See Model source code
The Model class is more of a work in progress. At this time, I have it implement my data connection class (PearDB) and store the handler. I store the db result as a private variable, so I can put a generic function "fetchToArray" that would loop through the result and put it in an array. I am using PearDB, which if you have a later version than I, you probably have access to the fetchAll method that would do the same thing and won't need this method in your model class. If you have any other generic methods (i.e. data checking, converting new lines etc) etc you would put them here.. I pass the array of data to the template, instead of trying to access the result set directly from the template (goal is to have as little logic in the template as possible).

    function fetchToArray() {
        $result_array = array();
        while($row = $this->result->fetchRow() ) {
            $result_array[] = $row;
        }
        return $result_array;
    }

Read Part 2

Edited: Figured out how to make code look good :)