I've been looking again at writing the developer documentation for emoncms, in particular Id like to document how to build the core framework from scratch, explaining the design decisions and implementation of things like the front controller, modules folder structure, MVC pattern.
In doing this exercise and reading up more widely about the various parts I started to get ideas for improvements.
"...Think about the change in mindset: no server-side templating… n o n e !"
The framework was initially built with server side templating in mind with the result of the model being passed to a view and the view being constructed with php. The current emoncms application architecture
documentation page reflects this idea, see the Views section in particular which shows a minimal example of creating a feed list using php.
Letting go of the idea that we might want to do server side php templating for most of the module views and reassessing the framework controller code in particular, the following as described on the controller part of the application architecture page no longer makes much sense:
if ($action == 'list' && $_SESSION['read'])
$feeds = get_user_feeds($_SESSION['userid']);
if ($format == 'json') $output = json_encode($feeds);
if ($format == 'html') $output = view("feed/list_view.php", array('feeds' => $feeds));
Here in response to a request from the client for a feed list we first get the data from the model and second either output it as json or wrap it in a view. But if the view no longer needs the feeds array passed to it (as it is getting the feeds data via an AJAX request) it makes no sense for the view to be called after getting the data from the model.
So I think a clearer structure for the controller is to divide it into two parts:
The first part deals with html page requests and is essentially loading the client side application from the server to the client:
if ($format == 'html')
if ($action == 'list') $output = view("feed/list_view.php", array());
if ($action == 'view') ...
The second part placed directly below the above in the controller deals with the JSON API to the model
if ($format == 'json')
if ($action == 'get') $result = get_feed(get('userid'),get('feedid'));
if ($action == 'list') $result = get_user_feeds(get('userid'));
$output = json_encode($result);
2) Straight mysqli instead of db.php abstraction
While rewriting the core framework from scratch it hit me that the db.php abstraction I created that converts mysqli class calls into global scope db_query etc functions is not really that useful and probably just confusing. db.php never did anything useful on top of mysqli like input sanitisation or anything like that so I think it would just be better to write straight mysqli.
Which leads on to the next point:
3) Models as classes
After using the mysqli class with the $mysqli->query() $class->method() type interface I started to experiment with using php classes for the emoncms models instead of just a file full of functions. Here's an example for the feed class with only one method for loading a users feed list (notice also how $mysqli is passed into the class for use)
public function __construct($mysqli)
$this->mysqli = $mysqli;
public function list($userid)
$feeds = array();
$result = $this->mysqli->query("SELECT * FROM feeds WHERE `userid` = '$userid');
while ($row = $result->fetch_object()) $feeds = $row;
To use this in the application we first create an instance of the class
$feed = new Feed($mysqli);
and then call the methods needed:
$result = $feed->list($userid);
This gives us a nice interface to the feed model in the rest of the application, it's a clearer naming convention model_name->method_name() and its clearer that model methods and properties belong to that model. There are also a whole load of other potential benefits as time goes on such as extending the class and so on (all standard stuff in most frameworks)
4) The fat model and thin controller
In reading more on the model view controller pattern I came across this article which really made a lot of sense to me: http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstood-and-unappreciated/
The question of what should be in the controller and what should be in the model is something that I had been a bit unsure about and so far I have usually put input validation and any error reporting in the controller while trying to confine the model to primarily data access.
But looking again at this and with the clarity of that article, it makes sense to me that input validation and error reporting should be in the model instead.
When coupled with the class based model that model then becomes a very complete and portable class that can be used in different applications or frameworks as the article suggests with all the validation and error reporting intact.
The controller's role then becomes: translation of the external http api to model method calls , fetching of input via $_GET and $_POST and passing these to the model method parameters and checking to see if the user has the correct privileges to call the model method.
5) php code formatting standards
Here's another interesting resource I came across only yesterday phptherightway.com
. There's lots of valuable information on there including details on 4 standards including a code formatting standard for php produced by many of the large php frameworks and application projects, I think it would be good to adopt these in emoncms.
On the client
Next steps...One of the good things about the server side changes proposed above is that many of them are only minor changes to existing code and they can be introduced incrementally, so we can run old code alongside new.