Performance Zone is brought to you in partnership with:

Leigh has been in the technology industry for over 15 years, writing marketing and technical documentation for Sun Microsystems, Wells Fargo, and more. She currently works at New Relic as a Marketing Manager. Leigh is a DZone MVB and is not an employee of DZone and has posted 106 posts at DZone. You can read more from them at their website. View Full User Profile

Getting Started with Drupal, Part 1

08.29.2012
| 4299 views |
  • submit to reddit

This is the first of two posts in the series Getting Started with Drupal, by guest writer Tobias Sjösten. Tobias is a web technician and open source aficionado who specializes in the LAMP stack, with Symfony and Drupal being especially close to his heart. He writes code in Vim, plays MUDs in gnome-terminal and naturally believes a well-configured text interface trumps its graphical equivalent any day of the week.

If you’re working on anything web related, it’s virtually impossible to miss the Drupal invasion of the past few years. Drupal is a PHP-based, open source platform built by thousands of passionate developers from all over the world. Known as a Content Management System (CMS), Drupal excels at creating websites, blogs and intranets. But it can also be used for so much more. Today, Drupal powers a whopping 2% of all the sites in the world, including some major installations like The Economist, MTV and the White House.

A popular slogan in Drupal-land is “come for the software, stay for the community.” This speaks volumes about just how inclusive the community is. Drupal.org has over 648,000 user accounts and 10,000 developer accounts. And as of March 2012, there are more that 15,648 community-contributed add-ons (contrib modules) that are available to customize Dupal’s behavior and appearance, add new features, or alter and extend its core capabilities. The last DrupalCon in Denver gathered over 3,000 attendees.

Learning to develop in Drupal has a steep learning curve. I believe this is because it does things very differently than other systems. While this can be challenging to an experienced developer, there are numerous resources to learn from. And I hope this post will give you a bird’s eye view of Drupal’s many parts and how they all come together to create one of the greatest web systems out there.

Learning Curve

Contrib: Building Blocks for Drupal Development
Normally with extendable open source systems, you have a community contributing “third party” plugins or extensions. In Drupal, these are called modules and the ones not shipped with the core Drupal installation are called contribution modules (contrib modules).

But here’s a very important distinction to be made. Contrib modules are not separate from Drupal the same way they are used in other communities. Instead this is an area where new ideas are bred and special use cases are handled. This is a vital part of the ecosystem – for every new major version of Drupal, some contrib modules are refactored and made part of the core.

If you install Drupal core as it is, you’d be able to create content and manage it to some extent. But let’s be honest, you’d create a rather crappy website. Instead what you should do is use both core and contrib modules as the building blocks of your site. By cherry picking them, you can build the exact site and functionality you want.

Many in the community label Drupal a Content Management Framework instead of a CMS. This description better reflects how you actually need to build the CMS yourself and how Drupal is a box of Legos you can use to do so. But as any ten-year old kid can tell you, you need to know which parts you need before you can build an awesome spaceship.

Entities and Fields
By definition, a CMS is all about content. In Drupal your content is packed into entities of different types, ranging from users and comments to nodes and taxonomies. These are abstract data types, representing a single piece of content.

From Drupal core you have a couple of modules like user.module and node.module which integrates with the Entity API to provide their own types. This API allows anyone to easily create custom entity types for special edge cases, using hook entity info(). More on this later.

By default your entities can automatically be retrieved from storage via entity_load(). However if you also install entity.module, then all entities are also given a full programmatic CRUD interface, to Create, Retrieve, Update and Delete instances of the given type.

The node entity type is to most sites the central type — it’s what editors normally create on a daily basis. Nodes are further broken down in bundles — a type of data template for your content. These can be anything from articles, FAQ pages, interviews, podcast episodes, etc. This all depends on your unique site.

Entities in and of themselves are just bare, boring objects. In order to save any meaningful data to an entity bundle you may add fields to it. An article could for example need a header image and a body text, while a user might require a name and a website address.

Fields are an examples of how contrib modules work. They were introduced way back in Drupal 5 by the CCK module. It was such a success with the community that the module was quickly adopted and kept through Drupal 6. Then it integrated into the core for Drupal 7, with the Field API.

The way it works is that modules define field types, like an image field, which can then be attached to a bundle and named “header image” for an article. When you then go and create an article, the field will be instantiated to hold that really cool cat picture.

Other field types include links, email address, geographic data, etc. Of course you can also add your own if you find that the plethora of contrib modules can’t cover your specific needs

Views for Lists
Now that you have your entities sorted, you will naturally want to list them and your other data too – whether it’s for a front page article listing, a “who’s online” list or a tag cloud. This is done using Views, a pluggable list generator module.

Roughly speaking Views work in two steps. First it takes your configuration and builds a query from it, which is sent to the backend. Your backend is normally a MySQL database, but it could just as well be a web service, an XML file, FTP server, etc. Views doesn’t care — it’s pluggable, remember? Second it receives the query result and transforms this into a list in your preferred format, ranging from your vanilla HTML <ul> lists to JSON and RSS.

As with most things in Drupal, you will create your views using a web based UI. But what’s most interest for us as developers is what’s happening behind the scenes. In the case of Views, you will basically configure a view object, consisting of handlers for filters, fields and sorting, styles for its output and various configurations.

A Views handler is basically a class that can query the user for configuration and then help build the query. There are field handlers that adds data to what the query returns, sort handlers to manage the ordering of results, relationship handlers which pull in extra data in related tables, filter handlers that sift the results to only pick specific ones, and so on.

Modules bringing a new type of entity field also often contain Views plugins for filtering on those fields, styles to format the fields and so on. This modularity means that when you have an edge case that isn’t covered by the default plugins, you can easily hook into Views and extend it any way you want.

Opposed to most everything else in Drupal, Views are very heavy on the object orientation. Your views are objects and their handlers, styles and plugins are objects. Everything is tied together by hooks (see below), which explains their individual module’s data structure, relation to other data and where to inject the various objects to do their job.

As always, database interactions will most likely be the biggest bottlenecks in your applications and because of this Views has built in support for caching. It works in two layers, where you can cache the raw results of the generated query and its themes output, individually. Of course the caching is pluggable as well, so you are able to extend and change the logic if you’re not happy with the default options.

Coming Up
Next week I will dig a little deeper into these subjects

Export with Features

Everything in Drupal is built through the web interface. Or should be, rather, since one common pitfall for many newcomers is to start digging into code and program all your features yourself. This is a big no-no and goes against The Drupal Way paradigm. This is an approach of building with existing blocks wherever possible to leverage all the work others have already done and will keep doing in the future.

But how will you ship it if everything you build is configured in the database? In particular — how will you ship continuous updates to an already deployed site? And no, building in production is never an option.

The answer is Features, another contrib module that allows you to export database configuration, diff between your export and the database, and flush the database configurations in favor of your exports. Together this gives you all the tools you need to work The Drupal Way with an easy point-and-click interface, while keeping all the benefits of having your site in code.

You also no longer have to make heavy database queries to put together your configuration, because they can be read from a file instead. Sure, disk I/O is also slow but with an opcodecache, like APC, that’s no longer and argument. Because you’re not running PHP without an opcode cache, are you?

I’d like to think that Features turns Drupal into one giant scaffolding machine. Definitely in a good way!

Extending Drupal

So it’s not a good idea to just dive head first into programming Drupal. Though for some cases you have no option but to do just that. Despite my definite bias towards Drupal, I honestly think for projects with a lot of these cases you should take a long, hard look at the requirements and perhaps consider other platforms to build upon.

If you still feel Drupal is a good choice then you are certainly covered as far as extensibility goes. Apart from being a box of blocks for builders to assemble, the platform also sports a nice base framework with several extension points for custom code.

In the majority of cases this means hooks – callback functions named in a specific format. It relies on string substitution magic and lots of function_exists() calls. In my opinion this is one of darkest corners of Drupalverse, but on the plus side it makes it really easy for beginners to jump right into Drupal development.

To understand how these hooks work in practice let’s say for example that you’re creating a module named newrelic. In it you want to run a piece of code on every incoming request and for that you decide to implement hook_boot(). So you open up your newrelic.module file (the module’s base PHP script) and enter the following:

<?php
function newrelic_boot() {
echo ‘Hello world!’;
}

And that’s it — you have now extended Drupal to print “Hello world!” on every page! Perhaps not the most useful extension, but still, you get the point.

A complete list of all hooks in Drupal core can be found at api.drupal.org. Also see example.module, which is a collection of examples and best practices for how you can extend Drupal with your custom modules.

If you’re someone coming in from an object oriented world, you may become confused by the data model in Drupal where the primary structure is an arbitrary array. It makes it impossible to code by contract and your code will consist of a lot of empty() and isset() calls, just to verify data integrity. This spaghetti architecture was amusingly highlighted by a recent April Fools joke.

But it does have its advantages, especially when it comes how easy it is to override core and contrib modules. Let’s say for example that you want to take over the login page of Drupal and replace it with your own. Then you first have a look at how user.module defines the page in its hook_menu() implementation.

function user_menu() {
return array(
‘user/login’ => array(
‘title’ => ‘Login’,
‘page callback’ => ‘user_page’,
),
);
}

Here it says that when someone visits example.com/user/login, the callback user_page() will be executed. If we want to replace that with our own callback we need to implement hook_menu_alter().

function newrelic_menu_alter(&$items) {
$items[‘user/login’][‘page callback’] = ‘newrelic_page’;
}

And all of a sudden, all visits to example.com/user/login will cause newrelic_page() to be called instead. Dead simple! This hook_x() -> hook_x_alter() pattern is very common in Drupal.

Premature Optimization is Evil
Drupal is very general purpose platform. Because of this it has been necessary to introduce several layers of abstraction, to make it suit as many use cases as possible. Of course in many cases this also means a severe hit in performance.

I agree with the critique that Drupal can be very slow. But I also firmly believe there is nothing you cannot fix and Drupal even makes this a relatively easy task. How to boost your performance is a subject for another article however. The best you can do is to remember that premature optimization is evil and instead you should focus on bottlenecks later when and if there really is a problem.

Until then — get to know your building blocks and keep scaffolding your site!

 

 

 

Published at DZone with permission of Leigh Shevchik, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)