Archive for the 'php' Category

Writing a Minimalistic MVC Framework in PHP

Wednesday, October 22nd, 2008

This is an outcome of a conversation I had recently. Apparently saying that MVC is a fairly simple concept is some sort of blasphemy. But it is. You really don’t need to use the almighty RAILS or a rails like framework like CakePHP in order to the whole Model, View, Controller separation. That’s the beauty of the idea - you can write your own MVC framework from scratch quite easily. In fact, sometimes it is probably preferable to do so. It’s true that you should avoid reinventing the wheel but sometimes you just want lean, minimalistic code with as few dependencies as possible. This is where you would do something like the example below.

This is a bare bones minimalistic core of a MVC system. It’s the index file - the driver or super-controller whatever you want to call it. Users will hit this page, and it will hand off the control to an appropriate Controller class. Thanks to the malleability of PHP this can be accomplished in just few simple lines:

<?php
 
define("COMMON", "/path/to/common/includes/");
 
include COMMON."Util.class.php";
 
if(empty($_GET["module"]))
   die("   <h1>Error: No Module Specified</h1>
            <p>Sorry, no module was specified.</p>
            <p>Please check your URL</p>");
 
if(empty($_GET["action"]))
   die("   <h1>Error: No Action Specified</h1>
            <p>Sorry, no action was specified.</p>
            <p>Please check your URL</p>");
 
$module = Util::sanitize($_GET["module"]);
$action = Util::sanitize($_GET["action"]);
 
$controller = $module."DefaultController";
 
if(file_exists("controllers/$controller.php"))
{
   include "controllers/$controller.php";    
   $active_controller = new $controller();
 
   if(!method_exists($active_controller, $action))
      die("    <h1>Error: Action Not Defined</h1>
                <p>Sorry, the action <strong>$action</strong>
                is not defined in <strong>$module</strong>.</p>
                <p>Please check your URL</p>");
   else    
      $active_controller->$action($_GET);
}
else
   die("   <h1>Error: Module Not Found</h1>
            <p>Sorry, module <strong>$module</strong> 
            does not exist.</p>
            <p>Please check your URL</p>");
?>

Note that I’m using some shortcuts here. For example I assume that you can figure out for yourself how to sanitize user input strings. I moved that functionality to the Util class which I import up top. You probably figured it out already, but if you didn’t this is essentially the folder structure you will need to have in your webroot directory:

croppercapture97.jpg

The rest of it should be straightforward. For example, let’s say you access this page with the following URI:

http://example.com/?module=user&action=view

This will trigger our file to try to locate the file user.php in the sub-folder controllers and import it. Then it will assume that the file contains a class user and will attempt to initialize it. Note that I did this in PHP4 so I’m using the old style constructors. You can easily modify it for PHP5. Finally, it will check if the newly created instance contains the method view and will attempt to execute it.

The controller class would then initialize a model class which would query the DB for user information, do whatever processing needs to be done and then pull in a View class which would deal with the displaying of the data on the page. It would probably utilize some templating scheme.

I’d actually implement a base class (let’s name it DefaultController) which would be the parent for all the other controller classes. In it I would implement all the basic CRUD functions in the most generic way possible. This way, when you decide to add a new controller to your project you can simply create an empty class stub which extends DefaultController and still have some functionality there. A very simplistic controller class would look something like this:

class DefaultController
{
  var $model;
  var $view;
 
  function DefaultController()
  {
    // find out the name of this module so that we can apply it in other places
    $module = substr(get_class($this), 0, strpos(get_class($this), "controller"));
 
    $model_name = $module."Model";
    $view_name = $module."View";
 
    include "models/$model_name.php";
    include "views/$view_name.php";
 
    $this->model = new $model_name();
    $this->view = new $view_name();
 
  }
 
  function read($args)
  {
    if(empty($_GET["id"]))
        $this->idError();
 
    $id = Util::sanitize($_GET["id"]);
    $this->model->populateFromDB($id);
    $this->view->render("read", $this->model);
  }
 
  function update($args)
  {
    if(empty($_GET["id"]))
        $this->idError();
 
 
    if(!empty($_POST))
    {
        $this->model->populate($_POST);
        $this->model->update();
    }
 
    $id = Util::sanitize($_GET["id"]);
    $this->model->populateFromDB($id);
    $this->view->render("update", $this->model);
 
  }
 
  function create($args)
  {
    if(!empty($_POST))
    {
        $this->model->populate($_POST);
        $new_id = $this->model->create();
        $this->view->render("thankYou", array("caption" => "Record Inserted", "id" => $new_id));
    }
    else
    {
        $this->view->render("create", $this->model);
    }
 
  }
 
  function delete($args)
  {
    if(empty($_POST))
    {
        if(empty($_GET["id"]))
            $this->idError();
 
        $id = Util::sanitize($_GET["id"]);
        $this->model->populateFromDB($id);
        $this->view->render("delete", $this->model);
    }
    else
    {
        $this->model->populate($_POST);
        $this->model->delete();
        $this->view->render("thankYou", array("caption" => "Record Deleted"));
    }
 
  }
 
  function idError()
  {
    die("<h1>No Record Specified</h1> <p>You need to specify a record ID to perform this action.</p>");
  }
 
}

Again, this is really minimalistic code. As you can see there is no error checking and no validation. Most of the time I’m delegating control to other classes and making even more assumptions. For example I’m assuming that a model class would have methods such as populate (which would essentially pre-populate it’s fields from an associative array passed in as an argument) and populateFromDB which would query the database and populate it by using the stored data. You can’t really make the models too generic since their structure will be based on the database table layout. You could probably try something clever - such as using an associative array instead of defining fields of all the database columns. This way you could have a fairly generic structure.

class DefaultModel
{
  var $fields;
  var $table_name;       
  var $db;     
 
  include COMMON."config.php";
  include COMMON."MyDatabase.class.php";
 
  function DefaultModel()
  {
    $this->table_name = substr(get_class($this), 0, strpos(get_class($this), "model"));        
    $this->fields = array(); // associative array
 
    // the database stuff is defined in config.php imported above	    
    $this->db = new MyDatabase(__DB_HOST__, __DB_DATABASE__, __DB_USER__, __DB_PASSWORD__);
    $this->db->dbconnect();          
  }
 
  function populateFromDB($id)
  {
    $results = $this->db->query_into_array("SELECT * FROM ".$this->table_name." WHERE id='$id'");
    $this->populate($results);
  }
 
  function populate($array)
  {
    foreach($this->fields as $key => $val)
       if(@key_exists($key, $array))
         $this->fields[$key]["value"] = $array["$key"];           
  }
 
  function insert()
  {
    $sql = "INSERT INTO ".$this->table_name." (submitted_on";
 
    foreach($this->fields as $key => $row)
      if($key != "id" and $key!='submitted_on' and $key!="last_updated_on")
        $sql .= ", $key";
 
 
 
      $sql .= ") VALUES (NOW()";
 
      foreach($this->fields as $key => $row)
        if($key != "id" and $key!='submitted_on' and $key!="last_updated_on")
          $sql .= ", '$row[value]'";
 
      $sql .= ")";
 
      $this->db->query($sql);
 
      return mysql_insert_id($this->db->getLink());
  }
 
  function update()
  {       
    $sql = "UPDATE ".$this->table_name." set last_updated_on=NOW()";
 
    foreach($this->fields as $key => $row)
      if($key != "id" and $key!='submitted_on' and $key!="last_updated_on")
        $sql .= ", $key='$row[value]'";
 
    $sql .= " where id='".$this->fields["id"]["value"]."'";
 
    $this->db->query($sql);
  }
 
  function delete()
  {    
    $this->db->query("DELETE FROM ".$this->table_name." WHERE id='".$this->fields["id"]["value"]."'");
  }
 
}

Note that I’m using a made up wrapper class instead of calling MySQL functions directly. This is just something that I did ages ago - I created a generic database class to interface with my code. Now whenever I switch database engines all I need to do is re-implement that class using appropriate syntax. Since all my SQL is going through that class I can even intercept it and correct illegal statements. For example my code might be using MySQL specific keywords, but the Postgress implementation of MyDatabase will automatically transform these queries into something that Postgress understands.

Then again, you may not want to do that. Parametrized queries may be a better idea here. They would be yet another step of abstraction. You could establish some common naming conventions then define parametrized queries in each database to follow them and simply have your wrapper class call them by name instead of actually building SQL queries.

Other than that the class is fairly generic - you will have to define the fields array on your own which can be easily done in the child class’ constructor. It’s not ActiveRecord or anything so there will be a considerable amount of work involved setting it up each time but it is serviceable.

I’m nor going to do a View class here because this post is getting crowded with code. But you get the idea - I’d use the same methodology as above, define as many generic methods as possible and then override them as needed in child classes.

I’m not sure how projects like CakePHP implement their MVC model. This is just an example of how I would go about developing one if I had to. It is probably very simplistic and unsophisticated compared to the other stuff available out there. But that’s sort of the point. Anyone can implement an MVC framework of sorts - for better or for worse. This one is mine. Yours may be very different but that’s ok. Constructive criticism is as always appreciated. Just remember that I pretty much pulled it out of my ass during a lunch break sort of as a proof that it is really not that complicated.

PHP: File Download Script - Straming Binary Data to the Browser

Monday, October 13th, 2008

I don’t think I have posted this snipped of code here yet. It is old as hell, but I use it all over the place lately so I figured I just post it here for future reference.

The script below solves the age old problem of making bunch of files accessible to your users without dumping them in a publicly accessible directory (files, not users). For example, you have bunch of PDF documents you don’t want to be indexed by Google, or directly linked to from other websites. What you want is to allow certain users to download them after logging into your web app and checking their cridentials. How do you do that?

Well, the simplest thing to do is to put them in some directory outside of your web root. Set up .htaccess (or whatever you use) to disallow any connection to that folder from the outside world. The only machine with access to these files should be localhost. Then you do some PHP magic in your application to stream the file into the browser upon successful authentication.

The streaming part is actually pretty straightforward - it is a simple combination of the print and fread commands. The convoluted part is convincing your browser to actually initiate file download instead of just dumping ASCII gibberish onto the page for binary files. This is accomplished by sending bunch of headers to the browser prior to streaming the files. The headers are different for IE and the rest of the world but this is pretty much what I ended up with after a lot of trial and error:

// change these to whatever is appropriate in your code
$my_place = "/path/to/the/file/"; // directory of your file 
$my_file = "filename.ext"; // your file
 
$my_path = $my_place.$my_file;
 
header("Pragma: public");
header("Expires: 0");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: pre-check=0, post-check=0, max-age=0', false);
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
$browser = $_SERVER['HTTP_USER_AGENT'];
 
if(preg_match('/MSIE 5.5/', $browser) || preg_match('/MSIE 6.0/', $browser))
{
  header('Pragma: private');
  // the c in control is lowercase, didnt work for me with uppercase
  header('Cache-control: private, must-revalidate');
  // MUST be a number for IE
  header("Content-Length: ".filesize($my_path)); 
  header('Content-Type: application/x-download');
  header('Content-Disposition: attachment; filename="'.$my_file.'"');
}
else
{
  header("Content-Length: ".(string)(filesize($my_path)));
  header('Content-Type: application/x-download');
  header('Content-Disposition: attachment; filename="'.$my_file.'"');
}
 
header('Content-Transfer-Encoding: binary');
 
if ($file = fopen($my_path, 'rb'))
{
  while(!feof($file) and (connection_status()==0))
  {
     print(fread($file, filesize($my_path));
     flush();
  }
  fclose($file);
}

I found these headers to work for me. Your millage may vary. I tested the script above in IE 6 and 7, Firefox 2.x and 3.x, Konqueror 3.5.8 and Chrome 0.2.149.30 and experienced no problems. As usual, I’m always open to constructive criticism and better solutions in the comments. Let me know what you think!

WIMP or WAMP?

Thursday, July 17th, 2008

For the past few years I have been running some software on a WIMP stack. They have been working quite well. I never had any issues with the technology stack itself. Or rather the only issues I had at times stemmed from the fact that a lot of PHP apps automatically assume that you are running Apache. So lately I had this crazy idea to try switching things around and running things on top of a WAMP stack. Here the thing though…

Long, long time ago, in a galaxy far, far away - as as I call it “back in college” I participated in a discussion on this very topic. It started with the following statement:

“… and on top of that they are running Apache on windows which is kinda stupid!”

This was met with round of nods, and approving grunts from everyone. Since I was the youngest, dumbest and least informed person in the room, I nodded too. Then asked why was it stupid, trying to figure out whether or not I should immediately uninstall apache from my home desktop.

The answer I got was sort of convincing. Apache was never designed to be run on windows. It was ported back to windows - it works because of kludges and hacks were made. It will never be as efficient as a server designed from ground up for the platform. It won’t scale and etc.. This was followed by another round of nods. One again, since I was least experienced, and least knowledgeable person there I didn’t argue the point and taken it as a given. From that point I always tried to run pure LAMP when possible, and if I had to use windows then use WIMP instead of WAMP. And of course I always figured:

“I have this windows box here, and it comes with it’s own built in server, so why would I install another one on top of it”.

Now that I think about it, I can’t really find any empirical data - any tests, or benchmarks which would support the convincing IIS vs Apache argument from my distant past. There are millions of various arguments on which one is better out there but most of them boil down to “Apache is better because it is open sauce” or “IIS sux because it is from Micro$not” and so on. Serverwatch has a nice, objective cross comparison between the two - and if you look at it, you will see that both are almost equivalent when it boils down to features. IIS is better at running ASP, and integrating Windows specific stuff. Apache on the other hand is multi platform and integrates better with linux-y technologies.

I really believe that the whole “Apache is a port” logic is faulty. It is an open source project after all, and people have been successfully deploying it on Windows for years, even in production environments. I’m sure it grew up considerably in the last 6 years or so since I had that conversation too. So if it was flaky back then, I’m sure it is not flaky now.

What do you think? Is WAMP a viable option these days? Should people stick to WIMP? Or is WIMP the abomination here? Is PHP really better off pairing up with Apache? I’m throwing it out there because I honestly don’t know. On one hand, I don’t want to try to fix what is obviously not broken. On the other hand, perhaps running WAMP would be more beneficial in a long run. LAMP is not really an option at that location I’m afraid.

Design by Contract in PHP with Assertions

Thursday, June 5th, 2008

Recently I wrote about meta programming in php because my recent project involves quite a bit of it. I will probably write about it at some other point but it’s still in sort of early development stage. However while these techniques produce very compact and flexible code, they can also be hard to debug. Since code gets modified at runtime you can often run into situations where something gets passed to the wrong method and you don’t really know why and where. Each time I called some method, I was making certain assumptions as to the state of the program. For example, whether or not I am accessing the right type of class, or whether or not the method is called properly and etc. Here is a sample comment block from a function I wrote recently:

/**
 *  Returns an array built by querying another table. The name of the table is based on the
 *  foreign key passed in as an argument(param $name) which is expected to be in the form
 *  tablename_id. The method will import tablenameModel and tablenameView  classes, initializes
 *  them and run listRecords() method on the tableModel instance.
 *
 *  Note that tablenameModel and tablenameView classes must exist and be defined in files
 *  models/tablenameModel.php and views/tablenameView.php. The classes should be derived
 *  from DefaultModel and DefaultView respectively.
 *
 * @param string $name The name of the foreign key form tablename_id
 * @return array
 */

I’m assuming tons of things here. I’m expecting classes to be defined in certain files, I expecting them to be descendants of certain other classes, and I need the argument to be passed to me in a specific format. During normal execution all of these conditions should be met automatically. The correct files should be in the right place, because of the way the whole system is set up. The classes in question should extend the correct parents because that is the convention I’m using. Similarly, I’m also enforcing a convention that all foreign keys are ought to be named in the form tablename_id. So if someone passes me a parameter that is in the wrong form, or that does not have correctly defined Model and View classes associated with it, this is a big issue. This should never, ever happen at runtime.

How do I enforce these things though? I opted to take my comments and turn them into assertion statements. At some point this almost turned into sort of a Design by Contract methodology. Ensure preconditions, guarantee postconditions and etc.. Here is the method body itself:

function getComboBoxArrayFromOtherTable($name)
{
   assert('is_string($name)');
   assert('Util::EndsWith($name, \'_id\');');
 
   $tablename = substr($name, 0, strrpos($name, '_'));
   $modelname = $tablename."Model";
   $viewname = $tablename."View";
 
   assert('file_exists(\'models/\'.$modelname.\'.php\')');
   assert('file_exists(\'views/\'.$viewname.\'.php\')');
 
   include "models/$modelname.php";    
   $othermodel = new $modelname();
 
   include "views/$viewname.php";      
   $otherview = new $viewname();
 
   assert('is_a($othermodel, \'DefaultModel\');');
   assert('is_a($otherview, \'DefaultView\');');
 
   $othermodel->listRecords();
   return $othermodel->getComboArray();
}

I could of course throw exceptions, or make my script die() if these conditions were not meant. But as I said before, failure to meet the asserted conditions were was not really something that could be introduced by a user stumbling to a wrong URL or entering malformed data at runtime. Failing these assertions would be primarily caused by someone calling my methods improperly, or passing wrong arguments. In other words - programmer errors. And so, we spank the programmer rather than the user by using assertions which can be disabled in production code.

They are sort of sanity checks that make sure I’m using my own methods the way I originally intended them, and that I’m not really building system around some curious side effect happening deep inside my code that I never really intended for, but over a period of time grown to really on. Not to mention that they really help you write a self documenting code.

I often forget to spell out all my assumptions like in my code block above. This one is a nicely fleshed out because but not all of my comment blocks are this informative. In fact when I’m in a hurry I will sometimes write a single sentence or two just to have something show up in the doc file. Assertions however must be explicit, and really flesh out my pre-conditions and post conditions. So even if I didn’t write any documentation for a given method, someone could pick it up and work out at least partial (bare bones) documentation just by looking at some of these statements.

I haven’t really used assertions that much in my PHP code before. But with this project I’m totally sold on them.

Metaprogramming in PHP

Tuesday, May 27th, 2008

Not so long ago I wrote about few meta programming tricks in Javascript. These are really powerful programming techniques that let you create elegant frameworks with generic code that adapts to your needs at runtime. But Javascript is not the only language that can accomplish stuff like that. You can use pretty much the same tricks in PHP. Yes, you heard me right - the ugly cousin of Perl, and the most hated and most used server side language can do this stuff.

Let me start this with a real life problem which was very often pointed out as a flaw in PHP 4. As you can remember, in PHP 4 you defined a constructor of a class like this:

class Foo
{
   function Foo()
   {
      // initialize
   }
}

In other words construction was a function with the same name as a class. PHP 5 introduced new constructor semantics:

class Foo
{
   function __construct()
   {
      // initialize
   }
}

This was done to solve a problem that most PHP developers always had issues with - namely how to call the constructor of a parent, if you don’t know it’s name. In PHP 5 it is easy:

class Foo extends Bar
{
   function __construct()
   {
      // do something
      parent::__construct();
   }
}

Easy, peasey! How do we do that in PHP 4? Well, we either hard code it or use a little bit of meta programming:

class Foo extends Bar
{
   function Foo()
   {
      $parent_name = get_parent_class();
      parent::$parent_name();
   }
}

What would be the problem with simply hard-coding parent::Bar() here? Think about what will happen when you create subclass of Foo. SubFoo class will try to call function Bar() which does not exist in Foo. The way we route around this issue is utilization of variable functions. Let me try to make it clearer by using a much simpler example:

function foo() { echo "Hello World!"; }
 
$my_string = "foo";
 
$my_string(); // outputs Hello World!

In other worrds, if you put a set of parenthesis after a variable, PHP will try to evaluate that variable and use it as a function name. It works in similar way to the PHP method call_user_func which lets you pass in a string representation of a function name, and have it called for you. And since you can generate that string on the fly, it makes for some interesting programming techniques. For example you can create a nifty function like this one:

function foobar($my_class_name, $my_method_name)
{
   if(class_exists($my_class_name))
   {
      $my_object = new $my_class_name();
 
      if(method_exists($my_object, $my_method_name))
         $my_object->$my_method();
   }
}

This function takes two strings. One is a name of a class, and one is a name of a method. It then initializes the class if one exists, and then calls an instance method of that class specified by name. You can pass any class and any method name, and if they are correct, the method will be executed.

There is also something called variable variables that may often come in handy. For example consider the following:

$foo = 'bar'; 
$$foo = 'baz'; 
 
echo $bar;   // outputs baz
echo $$foo; // also outputs bas

The contents of $foo are evaluated prior to assignment in $$foo so it dynamically becomes $bar on runtime. Combine that with variable functions and you got yourself a whole arsenal of meta programming weapons. An if that’s not enough for you then there is eval - a function that takes a string and tries to evaluate it as PHP code. Eval has it’s own little quirks though, and may cause somewhat unique issues. For example, code that is built dynamically by concatenating strings is notoriously hard to debug. It also won’t be properly highlighted by the IDE, and it which makes properly formating and escaping it will be difficult. So it probably deserves it’s own post.

I won’t deny it - PHP is not the prettiest language, and the lack of namespaces in it’s function library makes for some colorful naming patterns. But it wouldn’t be so prevalent and so popular if it didn’t have a lot of power underneath the hood.