One of the hardest concepts for new users of Drupal to grasp is that Drupal is not a page management system but a content management system. That may seem obvious, but it's actually an important distinction; Drupal doesn't think in terms of pages but in pieces of content. Not every page that will be displayed is a piece of content, and not every piece of content will have a page.
To understand how to build pages in Drupal, it's important to understand the Drupal Stack; that is, the order in which a Drupal architect will approach a build-out. There are actually four separate and distinct concepts at work: Content, Data slices, Layout, and Display. (See Figure 1.)
- By Content, we mean the data model within Drupal. Generally this means nodes and fields—Drupal's primary content object—but in Drupal 7, it refers to any entity and entity type. This is the structure of the content we are managing and how different pieces of content inter-relate;
- Data slices are sections of our content that we want to display. In the vast majority of cases, these are defined using the Views module. Each of these slices ends up as a displayable chunk, such as a block or a page callback;
- Layout refers to how those displayable chunks are placed on the page. Generally there are two ways that is done in Drupal: either with the core blocks system or with the contributed Panels module;
As with most parts of web design, designing in layers allows for a more robust, flexible, and sustainable end product. Let's look at each in turn.
Content, of course, is the lifeblood of any content management system. Drupal goes a step further than simply defining each piece of content as an opaque blob, however, and allows for a robust definition of "content". Content, in Drupal 6, consisted of the node system and the Content Construction Kit (CCK) contributed module. In Drupal 7, most of CCK has been moved into core. Content now encompasses any type of Entity, including nodes, comments, taxonomy terms, and so forth, and all may potentially have Fields.
All entity types support a concept called bundles: A bundle is simply a sub-class of an entity with a given configuration, including a given definition of fields. (Not all entities support fields, but most do.) All instances of that entity will conform to one and only one node type. For the node system, bundles are called node types and individual objects are called nodes. An entity type will usually have under a dozen bundles, but could have hundreds of thousands of objects (such as nodes) that conform to one bundle or another.
Fields are the primary datum in Drupal. A field represents a rich data element, that is, email address, photo, and date rather than primitive data types such as "string", "file", or "integer". Fields can be single-value or multi-value. Most entities (although not all) are composed of one or more fields. For instance, a node of type (bundle) Event could be composed of a title, a description (text field), price (number field), date (date field), contact person (email field), and multiple URLs to related events (multi-value link field).
Critically, fields can be shared between different entities. For instance, a node type for "staff" could have fields first name, last name, office, and supervisor. A node type for "faculty" could have fields first name, last name, office, and title (Professor, Assistant Professor, etc.). The first name, last name, and office fields have the same semantic meaning in both node types. Supervisor and Title, while both text fields, do not have the same semantic meaning. Sharing the first name, last name, and office fields between both node types means we can search those fields across different node types. We'll see how that works in a moment when looking at data slices.
Examining the data we want to manage and mapping it into the appropriate entities and bundles—including the right fields—is the first step to a successful Drupal site. That process could be a simple one hour of button pushing or be a significant, but important, part of project strategy depending on how large or complex the site is.
Now that we have the structure of our data defined, we need some way to pull out the parts of it we want. In many cases we want to display a single piece of content on a page, with some formatting. In those cases nodes work well, as nodes automatically get a page created for them at node/[nid]. Very often, however, we want to show some subset of multiple objects; a summary view, a list of recent posts, a list of related objects, images in a gallery, etc. In all of these cases we want "a list of stuff", even if that list has only one item. And if we want a list, the Drupal go-to answer is the Views module.
Views can seem daunting at first, as it has many moving parts. However, Views has its own conceptual stack that makes it much more approachable: what, how, where.
It helps to visualize the content in Drupal as a giant spreadsheet. That is not how it is stored, of course, but conceptually imagine all nodes in one giant table, with each column corresponding to a field. Some nodes will have data only in some columns/fields, depending on their type. (See Figure 2)
Showing the entire set of data in the site at once is rarely useful, of course, so Views supports three kinds of filter to whittle down the list to only what we want.
- Filters to restrict the data set with hard coded values configured in the View;
- Exposed filters to allow a site viewer to configure the filter, say with a drop down box, to change what gets selected;
- Contextual filters (formerly known as arguments) to filter the View based on some information available when the View is run, such as the URL path or a node the View relates to.
Using filters, Views lets us control what gets displayed. For instance, we can filter our data set to show only nodes of type "event" (Figure 3), happening on certain days (Figure 4), and with a price less than $10 (Figure 5). We then tell Views what fields we want to display, in this case just the title, date, location, and price. (Figure 6). We exclude the body field for now as we just want to show a listing of events. We have now "sliced" our content down to just the pieces we want at the moment. We can also specify a sort order for our data; say, the first event by date first.
Finally, with a rendered representation of our data, we need to decide where to put it. In Views, that is handled via display plug-ins. Views comes with a few display plug-ins, to expose a View on its own page, as a block, as an RSS feed, etc. Others are provided by many other modules. (See Figure 8.)
The important point here is that each of those questions—what, how, where—is answered independently. We can usually change one without changing another. The same underlying content-finding mechanism can be used to build nearly any form of visual display. A blog roll, a photo gallery, a random page image, a calendar grid, all of these can be built with the same swiss army knife and customized to a site's specific needs. The ability to fully leverage Views is one of the most important reasons to spend the necessary time getting the right data model in place.
Once we have all our display components built, where do we put them? That is a question of page layout. Drupal offers one layout mechanism out of the box. By default, there is a single page layout consisting of a primary content area, controlled by the URL path, and several secondary content regions. (See Figure 9.) Into each of these regions can be placed Blocks. Blocks are, in Drupal-speak, secondary display components. In general they do not relate to the primary content area, nor to the context in which they are shown such as what "section" of a site they are in. Frequently, that is enough, and is exactly what we want. Some blocks, especially those produced by Views, have their own mechanisms to determine contextual information such as the page URL, the node being displayed in the main area, and so forth. There is no consistent system for that, but for a great many cases, it is sufficient.
The layout can vary somewhat between pages by controlling when given blocks will or will not be displayed. Drupal core provides a number of ways to control when a given block will display, such as only on certain node types, only for certain users, or only on certain path pages. For more complex controls, the Context module provides an alternate interface for placing and controlling the visibility of blocks. Between core and Context an impressive number of visual designs can be squeezed into a single layout template. Some layouts are more complex for core blocks to handle, however. In some cases there may be no primary content region at all. On a home page, for instance, there may be no content, just roll ups of upcoming events, latest news items, a slideshow, and so on. All of those can be built easily with Views, but how to get them on the page? For high-end layouts there is the Panels module.
Panels takes the page rendering process and turns it around. Rather than building a main content area and then adding secondary content around it, Panels starts with a layout and then places into it chunks called Panes. Panes are essentially super-blocks. Like blocks they are displayable chunks, but unlike blocks they can be placed multiple times in a layout, can respond to context in the page such as the URL or information derived from it, and so on. (See Figure 10.) They even support much more robust caching options than blocks do, which can greatly help with performance.
In Panels, there is no primary content region. A page can be laid out to include one large pane for a node display, or a node can be broken up by field into different panes. Or there could be no primary content on the page at all, just a series of panes for different Views, showing different slices of our content. (See how it all stacks up?)
Finally we come to the top layer of the stack: the display. This is the theme layer of Drupal, about which much is written elsewhere. Although the line between layout and display is sometimes fuzzy, where possible, it is good to try and treat them as separate.
One of Drupal's greatest strengths is how readily it can be reconfigured by an administrator with a few button clicks. That includes moving around blocks, placing new blocks, creating new layouts with Panels, adding fields to an existing node or other entity, and so on. A good theme addresses how a given page element should look, but not necessarily where it appears. That's because administrators can change where it appears at any moment, and they don't want their site's visual design to break down and cry as soon as they do so.
A good theme follows the principle of Sustainable Theming. That is, it doesn't specify precisely how every page should look. Rather, it defines the rules by which something should appear if it is in a given region. A good theme will display a menu block, for instance, in a sane fashion regardless of whether it is in the left sidebar, right sidebar, or a small panel pane on the home page.
"Sane fashion" may vary, depending on the region, but it should always work without breaking the page layout. Similarly, the theming treatment given to a node should withstand the administrator adding a new field to it at any time. It may not look completely awesome, but the new field should still "fit" visually in the page. Generally the best way to achieve that goal is to rely heavily on CSS rather than HTML markup for laying out a page, and not hand-crafting every template for its specific use case; as soon as that specific use case changes, the template no longer makes sense.
Bringing it together
That may seem like a lot to take in. Four layers, one of which has three more, plus multiple ways of laying out a page? I thought Drupal was supposed to be simple!
For most sites, it is. But even on a modest site, getting the most out of Drupal means understanding how to use the available tools to their best effect. By far, the most important step in building a Drupal site is figuring out the data model. A poorly thought out data model can result in a brittle, inextensible site that needs to be thrown out to add new features. A well-designed data model, on the other hand, can lend itself to building a surprising amount of functionality simply by pushing buttons in Views and placing a few blocks.
But what if your site starts with a design mockup, rather than a data model? That's fine. Go over the designs and identify: "How can I build this with Views?" "How can I place this with blocks?" "Will I need Panels for this page, or for all pages?" Working backwards from the design in this fashion can elicit a surprising amount of detail about a site's data model.
A good "measure twice, cut once" approach that considers the full Drupal stack and leverages each part to its full potential is they key to a successful project. Fortunately, it doesn't have to be difficult. With a good knowledge of the site needs, a data model can be built in a long afternoon. And with a good data model, most of the site can be built out using standard tools in a week, without ever touching a line of PHP.