Monday 1 July 2013

Drupal as a framework (the role of entities)

Introduction

This is my second post in a series of related posts about Drupal entities the first is here.

If Drupal was predominately a framework as opposed to a customisable CMS then you would expect that a skilled PHP programmer with a good understanding of appropriate design patterns from other frameworks (MVC etc.) could reasonably quickly start from scratch with Drupal to build a moderately complex and well designed website.

Unfortunately this is not the case at the moment, the learning curve for Drupal is still too steep for most people to pull this off. One aspect of the "Drupal way" is to not re-invent the the wheel and to use from the massive selection of community contributed modules to implement your required functionality, and this works well for relatively simple sites.

Of course you could point out that Drupal is essentially a CMS, but it is increasingly being used for functionality that goes far beyond a traditional CMS and in those cases it is fair to ask how does it stack up as a framework. Sometimes software like Drupal will also be described as a content management framework (CMF), it may put things in perspective to see a list of software that could be considered in a similar space.

Where Entities step in to raise the bar for Drupal is in the role of modelling data.

Sometimes you have to write code, maybe your requirements are not mainstream enough to have a custom module or you have to integrate with a bespoke API or your clients are using Newsweaver rather than MailChimp or you have to integrate a bunch of contrib. modules in a way that was never envisaged. Of course all those wonderful custom modules required development and Drupal core requires a continual injection of developers that can work on the next generation of Drupal required for the ever involving web.

Not surprisingly the higher paid developer roles expect you to write quite a lot of code...

A tale of two developers

If you have worked somewhere where multiple frameworks are used, you may have bumped into one of the following two developers, note these are extremes for illustrative purposes only (including fictitious names), most of us are a hybrid of the two. Also for this example both developers are expected to (or have experience of) developing reasonably-highly complex custom modules. In the case of Drupal it is sometimes difficult to define the line between Site Builder, Themer and Developer.

Arnold

Arnold is a master of pure programming, possessing Jedi skills, highly educated in software engineering and experienced in a number of pure frameworks he has a full understanding of principles such as:

  • MVC
  • Dependency injection
  • Observer patterns
  • Factory patterns
  • etc. etc.
in his mind Arnold looks something like the picture to the right. 

Dave

Dave comes from a variety of backgrounds, but has spent a lot of time working at the coalface, tight deadlines, a wide range of requirements. Dave found Drupal ticked a lot of his boxes early on and has stuck with it. Dave is a bit unclear about design patterns (dependency injection, hey I was young, I am clean now).  Dave has an uncanny knowledge of huge arrays used for configuration or passed into functions, he also "just knows without thinking" the correct way to do things in Drupal.

In his mind Dave looks somewhat like the picture to the right.


Not so different

In reality Arnold and Dave may not be so very different, they have differing backgrounds but both have worked hard to attain their skills and both can produce effective solutions in the right circumstances.

Quite possibly both them really look like this, the only way to tell them apart is that Dave is wearing "I Luv Drupal" underpants.

With a shared language and shared understanding Arnold may find Drupal a viable option for his projects and Dave may feel comfortable to pick up another framework occasionally when appropriate.

Drupal doesn't look like a framework

Some Arnolds can quickly learn to thrive in Drupal land, they see the hook system as type of  "Aspect Oriented" programming and learn to live with the niggles, hooks can certainly be very powerful. 

The problem most Arnolds have is that Drupal does not look like a framework some elements of it just look nasty. For example there is still too much of this type of thing:

$value = $node->field_site_company_colour['und'][0]['safe_value'];

Apparently Dave tells him this is not good and should be done more like as follows, although Arnold notes that Dave still occasionally writes things as above when in a hurry (but has to worry about $language or something 'in case we go multi-lingual'). When Arnold reads about the Field API it appears clunky and it appears that Arnold still spends too much time peering at dumps of huge arrays to work out where to get his data from:

$my_field_items = field_get_items('node', $node, 'field_my_field');
  
if ($my_field_items) {
  $my_field_first_item = reset($my_field_items);
  $my_field_value = $my_field_first_item['value'];
}

Arnold is also horrified when he sees things in the code that look far too much like SQL:

$node_title = db_query('SELECT title FROM {node} WHERE nid = :nid',
  array(':nid' => $nid))->fetchField();

When Arnold asks about data modelling why does Dave keep showing him how to customise page related content, at this point he starts mumbling about abstractions and object relational modelling, he is also worried that the data he has squirreled away in a nosql database is never going to be available to Drupal.

A couple of entity classes 

Explaining a couple of entity classes and an introduction makes all the difference to Arnold, now at least he is in more familiar territory and can begin to see how he can model his data in the Drupal application. Even more interesting for him is that now he sees classes he immediately understands that he can extend and modify the classes to make his own version if  he has to.

EntityFieldQuery

The EntityFieldQuery class allows Arnold to retrieve entities matching a given set of conditions. For example something like:

$query = new EntityFieldQuery();
$query
  ->entityCondition(‘entity_type’, node’)
  ->entityCondition(‘bundle’, article’)
  ->propertyCondition(‘status’, 1)
  ->propertyOrderBy(‘created’, DESC’)
  ->fieldCondition(‘field_us_state’, value’, array(‘CT’, NJ’, NY’))
  ->range(0,10);
$result = $query->execute();
$nids = array_keys($result[‘node’]);

In this case we retrieve an array of node ids that can be loaded with the appropriate node load function. Note that we don't need to know anything about SQL or the storage engine being used.

A series of two good links to learn more about EntityFieldQuery are:
http://www.phase2technology.com/blog/entityfieldquery-let-drupal-do-the-heavy-lifting-pt-1/
http://www.phase2technology.com/blog/entityfieldquery-let-drupal-do-the-heavy-lifting-pt-2/

EntityMetadataWrapper

The entityMetadataWrapper is provided by the Entity API contrib module. It acts a wrapper for retrieving properties and information about and entity. Once you have an entity you can wrap it with the wrapper which provides a standardised way of accessing field values and entities through an API

An example of use is included below:

$node_wrapper = entity_metadata_wrapper('node', $node);
$body_text = $node_wrapper->body->value();

A good post to learn more about the entityMetadataWrapper is here:

http://deeson-online.co.uk/labs/programatically-access-field-data-using-entitymetadatawrapper-drupal

Classes in conjunction with hooks

We all know that hacking core is bad right? In the past we have had hooks, alter hooks (to allow us to alter other peoples hooks), even hook_module_implements_alter() to allow us to hijack somebody Else's hook implementation. But now consider the extra power implied by:
class MyEntityFieldQuery extends EntityFieldQuery {

Up until now Arnold has only been shown Drupal hooks, which although good for many use cases are not always enough to allow him to customise his code as needed without hacking core or modifying contrib module code.

Classes on the other hand can be overridden and extended. Beyond the scope of this post (and current experience of the author) but Arnold already has his eye on DrupalEntityControllerInterface  because he thinks he can see a way via entities to get to that nosql database data he has. The class based nature of the entity code plays right into this strength.

The Drupal Entitycache module is a classic example of a combined approach, the module extends various entity controller classes to add its own functionality (a technique Arnold will be comfortable with) and then uses the entity info alter hook to replace entity controller classes for a number of entities with its's own version.


No comments: