Learn Drupal

March 1st, 2011

We're opening up the entire online video library (over 24 hours of video) for free on March 11th for the Drupalcon sprint day. If you plan on participating in any of the sprints, this is a great opportunity to have a quick visual reference library at your fingertips. If you won't be at Drupalcon, you still have full access and can use the day to build some new skills.

If you're currently a subscriber, one way you can help the sprinters is by compiling a list of the videos that have been most helpful to you and post it in your blogs or the BaM community support page. Then send me a link and I'll be sure to add a mention of it to a post that will go out sometime before the sprints. Quick tip: To get a link to a specific video, just right-click on its link on the home page and select "Copy link location".

First videos in the Drupal Theming Essentials series

This week we released the first 5 videos in the new Drupal Theming Essentials series. In this series, we're going to give you all the tools that you need to modify the output of virtually anything in Drupal, from blocks to nodes to links. More importantly, we'll help you answer some common questions like "Where do I put this modification?" or "Do I use a module or a theme for this" or "How to I hide that pesky RSS icon".

Here are some additional topics that we'll be covering over the next several weeks:

  • How to build a theme from scratch
  • The right way to modify or extend a theme
  • How to use sub-themes
  • Using template files and theming functions
  • Conceptual groundwork to get a better idea of where coding and designing end and where theming starts.
  • Lots, lots more!

And below is the list of new videos, in which we cover issues around the ambiguous nature of theming:

Who these theming videos are for and what they do (and don't) cover
In this video, we explain what these theming videos are doing on a site geared towards module building, and what we purposefully exclude in order to focus on the most common and important concepts and techniques. (FREE)

What is the difference between designing, theming and coding, and why do they overlap so much?
This video answers the question of why it is so difficult to draw a line between these different roles, and why do these roles exist in the first place. (FREE)

What are all of the different ways to modify Drupal output?
If you've ever found your head spinning as you attempt to figure out how to modify some output, it might be because there are so many possible approaches. In this video, we discuss different approaches including using CSS, installing contributed modules, and using alter functions within a module. (subscriber-only)

How to determine which method to use when modifying output
Once you're aware of the different approaches for modifying output, this video will help you answer the question of which method to chose for various situations. (subscriber-only)

A conceptual introduction to the Features module for exporting configuration options as code
In general, making output modifications with configuration changes is difficult to maintain and copy from one site to another. However, the Features module offers one solution for this, which may influence whether you take a modular or configuration-based approach to your modifications. (subscriber-only)

February 20th, 2011

Over the last two weeks, Build a Module.com has released 17 videos on how to use the File API in Drupal 7. This week we wrap the series up with 7 more videos, completing the final example where we build an image gallery with managed files completely outside of the node system. We also added a video on X-sendfile, the Apache mod that makes the private file system scream, and we open up the black box of stream wrapper code.

In addition to this release, the full collection of all 24 File API videos is also now available as a purchasable download.

How to use the EntityFieldQuery class to match certain criteria and display the results

In case you missed the previous announcements, below are the videos that are free for all visitors plus a couple that are available to mailing list subscribers:

The new videos

And below are the new videos. At this time, they're only available to subscribers, but we occasionally open up subscriber-only videos to the public for special occasions, so keep your ears out (or follow us on Twitter).

February 10th, 2011

Hot on the heels of our previous issuing of File API goodness comes 7 brand-spanking-new videos, starting with how to completely dominate unmanaged files, and wrapping up with tips on using and troubleshooting the private file system. This is good stuff!

There will be one more set of videos coming out next week to round things out, where we cover working with managed files (files with a database entry) and toss in some useful bits about improving private file performance and demystifying stream wrappers.

Here's the new videos:

February 10th, 2011

Last Friday we released a set of new videos called "Working with Files and the File API." This group of videos demonstrates some of the basics of working with files, including how to set permissions on files and folders, the difference between managed and unmanaged files in Drupal, plus a few other important bits. We begin an example to demonstrate a cohesive module using most aspects of the File API to create a gallery-style image manager, but without any nodes.

This send ends while we're working through the validation process on an unmanaged file form, and we'll continue this week and the next by building the same gallery system using managed files, and discussing a few additional topics like improving the performance of private files and diving into some stream wrapper code.

Don't let the terminology fool you into thinking this is boring stuff. Knowing how to work with files can be an extremely powerful tool in your developer toolbelt, and when you get done watching this entire series, you'll be able to easily and intelligently know what to do when you have digital assets to gather, move around or protect.

Below is a list of the new videos that were added, enjoy!

February 9th, 2011

The source code used in the current and upcoming File API videos has been added to the resource pack. Enjoy!

February 1st, 2011

Today I added a nice high-res Appple icon so that iPhones, iPads and iPod Touches can have a nice little faux app icon on their home screen. Check it out:

Build a Module iPhone App

The only reason I know this is possible is because I checked out the Drupal watchdog table to see what kind of 404 page not founds and PHP errors I might be inflicting on unsuspecting viewers and discovered multiple requests for a file called apple-touch-icon.png. Sure enough, as I found out here, there's a Add to Home Screen option in Mobile Safari, and it looks for this image to use as the app icon.

I first tried a 52x52px version, but it looked pretty grainy on my iPod Touch 4 retina display, so I created a 119x119px version and that's much more clean.

To make Build a Module ultra accessible on your iDevice, just do the following:

  1. Open up https://buildamodule.com in Mobile Safari.
  2. Touch the Add bookmark icon to open up the bookmark options.
  3. Touch the Add to Home Screen button
  4. By default, the title is Learn Drupal, but you can change this to something like Become Awesome.

That's it! Now you have the official Build a Module faux iPhone app at your fingertips wherever you go.

January 26th, 2011

Want to learn Drupal 7 development, but haven't had the time yet? Have a development team that needs to get on board with Drupal 7 fast? Are you teaching Drupal and need training material for your students?

Build a Module.com V.2 has been officially released, complete with over 12 hours and 130 new Drupal 7 development video tutorials. The training takes you all the way from building your first Drupal 7 module to really digging deep into the new Database API, the menu system, building forms, and there's even nearly 2 hours dedicated to getting up to speed with jQuery and JavaScript in Drupal 7.

The Build a Module.com site has been entirely revamped to include a super-clean interface for watching and browsing videos, new video organization, and a community forum for subscriber-to-subscriber support.

Tons of free Drupal development training material

There's over 5 hours of free videos available so you can learn a ton without having to purchase anything, though subscriptions, HD downloads as well as DVDs are available for full access to the videos. Once a purchase has been made, the entire source code for the examples used in the videos will be available for download so you can easily follow along.

Here's a sample of the free videos:

Introduction to Module Building

Coding standards, the Form API and the menu system:

Theming and the Database API

Working with users and nodes

Working with jQuery and JavaScript in Drupal 7

A few extras for newsletter subscribers

Signing up for the newsletter also gets you access to a number of other free videos, including:

Adding usability with the #state attribute
Learn how to build awesomely usable forms using the #state attribute to show and hide elements on demand.

Modifying forms with hook_form_alter()
Ever wanted to change a Drupal form, but didn't know how? Look no further, here's how.

Adding autocomplete to a text input
Take a look behind the magic of autocomplete inputs - awesome for search boxes, usernames and more.

Using the #ajax attribute for dynamic form building
How to build forms dynamically - add checkboxes, remove textareas, load new fieldsets, you name it. And all without a page reload. Slick!

How to use render arrays and tabs
I bet you're at least a bit curious about render arrays. They're a big deal, like you! Learn how to use them to allow your pages to be modified by other modules.

How to use sub-tabs
Tabs are nice, but what about tabs of tabs? Well, here you go.

How to load JavaScript after a page is done loading
Ever wanted to add Javascript and CSS on the fly, Ajax-style? It's super easy with Drupal 7, check it out.

Questions?

If you have any questions or have any material you'd like to see covered, please drop me a line.

December 30th, 2010

Drupal is rife with arrays, so knowing how to work with them effectively will open up some great possibilities for you. There's a lot you can do with arrays, but before you really dig in, here's a short article on how to find the contents of an array.

In Drupal, arrays are handled almost exclusively through vanilla PHP functions. Let's take a look at a common use of an array in Drupal - altering a form using hook_form_alter(). This example comes from the Advanced Poll module:

function advpoll_form_alter(&$form, $form_state, $form_id) {

The first value passed to this function is $form, which is an array containing all the elements in the form. The easiest way to browse the contents of this array is to use a PHP debugger, but we can also use a nice little function called var_dump() to output the array in a fairly readable format. Here's how you would use var_dump():

var_dump($form);

This will output a tree-like structure containing the values of the $form variable. Here's an example of what a partial var_dump() output looks like:

array
  'file_directory_path' => 
    array
      '#type' => string 'textfield' (length=9)
      '#title' => string 'File system path' (length=16)
      '#default_value' => string 'sites/default/files' (length=19)
      '#maxlength' => int 255
      '#description' => string 'A file system path where the files will be stored. This directory must exist and be writable by Drupal. If the download method is set to public, this directory must be relative to the Drupal installation directory and be accessible over the web. If the download method is set to private, this directory should not be accessible over the web. Changing this location will modify all download paths and may cause unexpected problems on an existing site.' (length=450)
      '#after_build' => 
        array
          0 => string 'system_check_directory' (length=22)

Items in the tree that aren't contained in quotes usually indicate the type of variable. In this case, the top-most variable is an array, and the array contains other arrays, some strings and an 'int' (integer) value. The next line indicates a key / value pair by linking the key 'file_directory_path' with the value - also an array - through the '=>' symbol. You can see that the output is indented to indicate when one variable is actually inside another variable. If you look down the output, you can see that there is one more array embedded in the embedded array. Arrays like this are called 'nested arrays', and arrays can be nested like this indefinitely. That makes them ideal candidates for organizing hierarchical data.

When you use var_dump() to output a array, you will likely need to view the source code in your browser to view the indentations. You can use var_dump() on any variable, and so it can also be very useful for getting the structure of an object.

In future posts, we'll cover some techniques for manipulating an array.

December 30th, 2010

It quite the challenge to build a path to a file in the Drupal system without the help of the API. In particular, if you're building a module that needs to work regardless of where a site puts their files, you might end up lost in a rabbit hole of API functions that sound like they might do the trick, but don't.

The function you need in your tool belt to create well-formed Drupal file paths is file_create_path(). Here's an example of how the Filefield CCK module uses file_create_path:

$file = file_create_path($file);

Let's take a look at the code and see what's going on here:

function file_create_path($dest = 0) {
  $file_path = file_directory_path();
  if (!$dest) {
    return $file_path;
  }
  // file_check_location() checks whether the destination is inside the Drupal files directory.
  if (file_check_location($dest, $file_path)) {
    return $dest;
  }
  // check if the destination is instead inside the Drupal temporary files directory.
  else if (file_check_location($dest, file_directory_temp())) {
    return $dest;
  }
  // Not found, try again with prefixed directory path.
  else if (file_check_location($file_path .'/'. $dest, $file_path)) {
    return $file_path .'/'. $dest;
  }
  // File not found.
  return FALSE;
}

The first line calls file_directory_path, which just grabs the value set on the admin/settings/file-system page of your site. Next, it runs through a series of checks to first insure that that the path hasn't already been appended with the file system directory, next to see if the file isn't stuck in the temporary file directory, and finally adds the system path to the file and returns the full path if the file exists.

One thing to note is that once you have your full path, you shouldn't have to add anything else to use it. file_create_path should work on it's own to give you the file path you need.

I've used this function when I have a file that I know will always be in the file directory, but can't be sure where that directory will be. It took me way too long to dig this information up. There are a couple of other useful file-related API calls that I discovered along the way, including:

  • file_create_url - Creates a link to download a file
  • file_check_path - Insures that the directory that contains the file is writable by Drupal
December 30th, 2010

Most PHP developers are initiated into the world of includes with the following:

include($file);

or

require($file);

The difference between include and require is subtle. Require - as the function name indicates - requires that the included file exist to continue the script. So, if require fails, the script stops. Using include will allow the script to continue. Most of the time, using require makes more sense because it's likely that the file we want to include includes some important information for the rest of the script.

After a while, most of us discover that we might be inadvertently including the same file several times, and learn some new functions to insure our files aren't being loaded multiple times, namely include_once and require_once to prevent

That's better, but when we start developing in Drupal, we're likely going to be stringing this along with some other functions to get the correct path to the file we need to include. There's a nice little function available for us in the Drupal API which simplifies this code. Here's an example from content.module in the CCK module of module_load_include:

module_load_include('inc', 'content', 'includes/content.node_form');

Let's take a quick look at the code behind the scenes:

function module_load_include($type, $module, $name = NULL) {
  if (empty($name)) {
    $name = $module;
  }

  $file = './'. drupal_get_path('module', $module) ."/$name.$type";

  if (is_file($file)) {
    require_once $file;
  }
  else {
    return FALSE;
  }
}

First, the function assumes that we'll be using an include file that has the same name as the module. If not, no problem, we just set the name explicitly in the third parameter.

Next, a path to the file is generated based on the module name we pass to the function. If you're still wrapping your mind around how to create portable paths in Drupal, this is a nice example. The dot-slash (./) indicates that the file should only be looked for in the current directory, and not in any shared PHP library directories. The drupal_get_path function is a nice API call to generate a path to a module or theme directory. Note that you have to supply the code with the extension for the included file, which will often be 'inc.'

Finally, the function checks to see if the file exists using is_file(). There is another function that operates similarly, called file_exists(), and the difference between the two is that file_exists will return TRUE if a file OR a directory exists with the name. If you know you're looking for a file, is_file usually makes more sense.

There we go, a nice little function to save you some code repetition that also gives you some ideas for best practices on including files.

December 30th, 2010

In this post, you'll learn how to manipulate arrays in Drupal. If you haven't already taken a look at How to find the structure of a Drupal array, give it a quick look over before continuing.

There are a number of useful PHP utilities for manipulating arrays. We're going to use the example here of hook_form_alter(), a hook supplied by Drupal to allow us to manipulate forms. Since forms are really just arrays of data, altering the structure of a form is synonymous with altering an array. Let's take a look at a simple $form array from the user login form, defined in user.module in the modules/user folder:

$form = array(
  '#action' => url($_GET['q'], array('query' => drupal_get_destination())),
  '#id' => 'user-login-form',
  '#validate' => user_login_default_validators(),
  '#submit' => array('user_login_submit'),
);
$form['name'] = array('#type' => 'textfield',
  '#title' => t('Username'),
  '#maxlength' => USERNAME_MAX_LENGTH,
  '#size' => 15,
  '#required' => TRUE,
);
$form['pass'] = array('#type' => 'password',
  '#title' => t('Password'),
  '#maxlength' => 60,
  '#size' => 15,
  '#required' => TRUE,
);
$form['submit'] = array('#type' => 'submit',
  '#value' => t('Log in'),
);

Adding an element to an array

In this example you can see that the $form variable is first defined, and then new variables are added to it by using the following structure:

$form[$key] = $value;

The important part here is that the $key is unique, otherwise the existing value for the key will be overwritten.

Replace an array value

That last example gives gives us a clue as to how we would override a array value. Say we wanted to replace the label on the 'Username' input to something like 'What should we call you?'. To do that, we'd do:

$form['name']['#title'] = 'What should we call you?';

Notice that we're having to change an array element that's within an array. We dig into the structure on an array using the [] brackets. Because $form['name'] is an array, and we need to identify the #title element in that array, we use $form['name']['#title'].

In Drupal, it's a convention to add a hash tag (#) to the beginning of variable names that correspond to a setting, rather than an element. This is done to avoid namespace collisions.
Removing an element from an array

To remove an item from an array, you can use the unset() function. Say we wanted to remove the password input from the above form. We'd do that with the following:

unset($form['pass']);

Moving an element off the end or beginning of an array

There are a couple of handy tools that you can use to move elements off of the beginning and end of an array - kind of tricky to do without the help of these functions. To remove the first element off an array, you would use the following:

array_shift($form);

This isn't very practical for our $form example, but believe me, it will come in handy down the road. And to remove an element off the end of an array, use the following:

array_pop($form);

These two functions also return the element that was removed, so if you wanted to do something with the element, just assign a variable to the function, as in the following:

$element_removed = array_pop($form);

There, now you're an array manipulation ninja. Go forth!

December 30th, 2010

Most of the time, 403 and 404 errors don't need to be dished out manually. Users will get a 404 when they hit a URL that doesn't correspond to an actual file or page, and will get a 403 when they are denied access through various access control utilities in Drupal. However, on occasion you'll need to explicitly send someone to a 404 or 403 error page, and in that case, drupal_not_found and drupal_access_denied are your friends. With them, you don't have to worry about manually settings headers or redirecting to the error page that's been defined in the error handling configuration.
Serving a 403 page with drupal_access_denied()

Let's take a look at an example of drupal_access_denied from the SimpleNews module:

// If non-admin is trying to edit someone else's subscription, access denied.
if ($user->uid && $user->uid != $subscription->uid && !user_access('administer simplenews subscriptions')) {
  drupal_access_denied();
  return;
}

In this example, a little logic is need to determine if a user has access. First, it checks to make sure the user is logged in, then insures that if the user editing the subscription doesn't have a particular permission, they get booted with a drupal_access_denied().

Note that the drupal_access_denied function will only print the 403 page, but will not stop the script from continuing. So, you need to make sure that the functionality you're preventing access to doesn't get run by using a return after the call.
Serving a 404 page with drupal_not_found()

Next, let's look at an example of drupal_not_found. This example comes from the Masquerade module:

$new_user = user_load(array('uid' => $uid));
if (!$new_user->uid) {
  return drupal_not_found();
}

The Masquerade module is checking to make sure that a user exists, before allowing access to a page specific to the user. If the user doesn't exist, then the page also doesn't exist, therefore the current user should get a 404. Notice that this snippet uses a slightly different syntax for the return. Instead of returning on a separate line, return is used on the function itself. drupal_not_found will not return any value, but the syntax still works and is slightly more elegant.

December 30th, 2010

It's tricker than it seems to get the URL to the current page you're on in Drupal, and the solution you use depends on what your goal is. Let's explore a couple of options. Let's say the URL to the current page is the following:

http://example.com/user?queryvar=1

Note that I've added a query string to demonstrate how it can complicate things. Let's look at the first option, which probably will work for us most of the time:

request_url();

The request_uri() function is a utility function supplied by Drupal for just this use. Here's what it returns:

/user?queryvar=1

We can go ahead and slip that right into a link, but to manipulate it would take some work. It's not a value we can pass into url() or l() and have work. And if we're not sure if there's going to be a query string, we can't just go and add to it without a check. Let's look at another option:

$_GET['q'];

This $_GET variable typically corresponds directly to the the path that you would pass to a url() or l() function, and in this case it would typically return the following:

user

This is something we can work with, but I've worked with several sites where the $_GET value doesn't necessarily correspond directly to the current page. For example, on the project that spurred this post, $_GET['q'] on /user will return /user/8423, which will return a different url if passed to url(). So, it didn't work for this particular case. The solution I found seems a little twisted, but here it is:

trim($_SERVER["REDIRECT_URL"], '/');

This returns the correct value for me every time, with the query string stripped off. It is an absolute URL, which means that before we trim the slash off of it, $_SERVER["REDIRECT_URL"] would return /user.

Good luck, and I hope you found this before totally blowing a fuse.

Add to playlist

Add to , or

Add to new playlist:

Add to playlist
This is a member-only feature
But, it's easy to become a member

Add to cart:

Syndicate content

Loading...
Contact us

Below are the supported keyboard shortcuts for our video player.

space
Start / stop video
shift
Go to next video
shift
Go to previous video
Increase or decrease player speed by 20%
Skip ahead or go back by 15 seconds
1...9
Jump to a percentage (2 is 20%, for example)
f
Toggle full screen
Videos Pricing More Search
BuildAModule Logo Icon BuildAModule Logo Icon
Become a member!
$29
1 month
$156
6 months
10% off
$276
12 months
20% off
All memberships come with the following:
24 / 7 access to the entire 1800+ video library
An innovative video player with a rolling transcript
Extensive Drupal and cross-platform training
A thorough and thoughtful training style
Progress tracking
Take notes on specific video sections
Intuitive multi-user management
How many users?
user
Go solo with a single user, or give multiple team members access through one account and get discounts by bundling multiple users into a single membership.